page%swap@Sun.COM (Bob Page) (05/09/89)
Submitted-by: utoddl@uncece.edu (Todd M. Lewis)
Posting-number: Volume 89, Issue 119
Archive-name: fun/maze.1
Here's a little ditty that builds mazes and lets you solve them. This
one is in C, and I even went back and made sure the comments were
usually close to what the code might have done at one time. I used
Manx, but conversion to other compilers should be trivial.
# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
# about.c
# maze.c
# stdhead.c
# makefile
# This is archive 1 of a 1-part kit.
# This archive created: Mon May 8 16:58:06 1989
echo "extracting about.c"
sed 's/^X//' << \SHAR_EOF > about.c
X#include <exec/types.h>
X#include <graphics/view.h>
X#include <intuition/intuition.h>
X#include <functions.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X
Xextern struct Window *window;
Xextern ULONG RangeRand();
Xextern struct TextAttr font;
X
Xcycle(color) int color;
X{ struct ColorMap *cm;
X struct ViewPort *vp;
X UWORD orig, r, g, b, ro, go, bo;
X int i;
X
X vp = ViewPortAddress( window );
X cm = vp -> ColorMap;
X
X orig = GetRGB4( cm, (LONG) color );
X b = (bo = (orig ) & 15);
X g = (go = (orig >> 4) & 15);
X r = (ro = (orig >> 8) & 15);
X
X for (i=0; i<1000; i++) {
X r = RangeRand(2L) * 15;
X g = RangeRand(2L) * 15;
X b = RangeRand(2L) * 15;
X SetRGB4(vp,(LONG)color,(LONG)r,(LONG)g,(LONG)b);
X }
X SetRGB4(vp,(LONG)color,(LONG)ro,(LONG)go,(LONG)bo);
X }
X
X#define reqW 544
X#define reqH 152
X#define centerX(chars) (reqW/2 - (chars)*8/2)
X#define centerXright(chars) (reqW - 111 - (chars)*8/2)
X#define centerXleft(chars) (111 - (chars)*8/2)
X
XSHORT reqborderXY[] = { 2,1, 541,1, 541,150, 2,150, 2,1 };
X
Xstruct Border reqborder = {
X 0,0, /* LeftEdge, TopEdge */
X 1,1, /* FrontPen, BackPen */
X JAM1, /* DrawMode */
X 5, /* Count */
X reqborderXY,/* SHORT *XY */
X NULL, /* NextBorder */
X };
X
XSHORT gadborderXY[] = { 2,1, 97,1, 97,28, 2,28, 2,1 };
X
Xstruct Border gadborder = {
X 2,1, /* LeftEdge, TopEdge */
X 1,2, /* FrontPen, BackPen */
X JAM2, /* DrawMode */
X 5, /* Count */
X gadborderXY, /* SHORT *XY */
X NULL, /* NextBorder */
X };
X
Xstruct IntuiText gadtext = {
X 1,2, /* FrontPen, BackPen */
X JAM1, /* DrawMode */
X 18,11, /* LeftEdge, TopEdge */
X &font, /* TextAttr *ITextFont */
X (UBYTE *) "Continue", /* IText */
X NULL, /* struct IntuiText *NextText */
X };
X
Xstruct Gadget aboutgad = {
X NULL, /* NextGadget */
X 222,117,100,30, /* LeftEdge, TopEdge, Width, Height */
X GADGHNONE, /* Flags */
X ENDGADGET | TOGGLESELECT, /* Activation Flags */
X REQGADGET | BOOLGADGET, /* GadgetType */
X (APTR)&gadborder, /* GadgetRender */
X NULL, /* SelectRender */
X &gadtext, /* GadgetText */
X NULL, /* MutualExclude */
X NULL, /* SpecialInfo */
X 0, /* GadgetID */
X NULL, /* UserData */
X };
X
Xstruct IntuiText ab_txt8= {
X 3,2, /* FrontPen, BackPen */
X JAM1, /* DrawMode */
X 20,102, /* LeftEdge, TopEdge */
X &font, /* TextAttr *ITextFont */
X (UBYTE *) "Comments and suggestions are welcome.", /* IText */
X NULL, /* struct IntuiText *NextText */
X };
Xstruct IntuiText ab_txt7= {
X 3,2, /* FrontPen, BackPen */
X JAM1, /* DrawMode */
X 20,92, /* LeftEdge, TopEdge */
X &font, /* TextAttr *ITextFont */
X (UBYTE *) "writing it. Please feel free to share it with your friends.", /* IText */
X &ab_txt8, /* struct IntuiText *NextText */
X };
Xstruct IntuiText ab_txt6= {
X 3,2, /* FrontPen, BackPen */
X JAM1, /* DrawMode */
X 20,82, /* LeftEdge, TopEdge */
X &font, /* TextAttr *ITextFont */
X (UBYTE *) " I hope you enjoy playing this game as much as I enjoyed", /* IText */
X &ab_txt7, /* struct IntuiText *NextText */
X };
Xstruct IntuiText ab_inst3= {
X 3,2, /* FrontPen, BackPen */
X JAM1, /* DrawMode */
X 20,68, /* LeftEdge, TopEdge */
X &font, /* TextAttr *ITextFont */
X (UBYTE *) "give you a hint. Select new mazes from the menu. Good luck!", /* IText */
X &ab_txt6, /* struct IntuiText *NextText */
X };
Xstruct IntuiText ab_inst2= {
X 3,2, /* FrontPen, BackPen */
X JAM1, /* DrawMode */
X 20,59, /* LeftEdge, TopEdge */
X &font, /* TextAttr *ITextFont */
X (UBYTE *) "red spot to the dark red spot. The left mouse button will", /* IText */
X &ab_inst3, /* struct IntuiText *NextText */
X };
Xstruct IntuiText ab_inst1= {
X 3,2, /* FrontPen, BackPen */
X JAM1, /* DrawMode */
X 20,50, /* LeftEdge, TopEdge */
X &font, /* TextAttr *ITextFont */
X (UBYTE *) " Move the mouse pointer through the maze from the bright", /* IText */
X &ab_inst2, /* struct IntuiText *NextText */
X };
Xstruct IntuiText ab_left2= {
X 3,2, /* FrontPen, BackPen */
X JAM1, /* DrawMode */
X centerXleft(19),120, /* LeftEdge, TopEdge */
X &font, /* TextAttr *ITextFont */
X (UBYTE *) "Usenet Distribution", /* IText */
X &ab_inst1, /* struct IntuiText *NextText */
X };
Xstruct IntuiText ab_left1= {
X 3,2, /* FrontPen, BackPen */
X JAM1, /* DrawMode */
X centerXleft(12),130, /* LeftEdge, TopEdge */
X &font, /* TextAttr *ITextFont */
X (UBYTE *) "Spring, 1989", /* IText */
X &ab_left2, /* struct IntuiText *NextText */
X };
Xstruct IntuiText ab_txt5= {
X 3,2, /* FrontPen, BackPen */
X JAM1, /* DrawMode */
X centerXright(24),140, /* LeftEdge, TopEdge */
X &font, /* TextAttr *ITextFont */
X (UBYTE *) "utoddl@ecsvax.uncecs.edu", /* IText */
X &ab_left1, /* struct IntuiText *NextText */
X };
Xstruct IntuiText ab_txt4= {
X 3,2, /* FrontPen, BackPen */
X JAM1, /* DrawMode */
X centerXright(20),130, /* LeftEdge, TopEdge */
X &font, /* TextAttr *ITextFont */
X (UBYTE *) "utoddl@ecsvax.BITNET", /* IText */
X &ab_txt5, /* struct IntuiText *NextText */
X };
Xstruct IntuiText ab_txt3= {
X 3,2, /* FrontPen, BackPen */
X JAM1, /* DrawMode */
X centerXright(21),120, /* LeftEdge, TopEdge */
X &font, /* TextAttr *ITextFont */
X (UBYTE *) "Author: Todd M. Lewis", /* IText */
X &ab_txt4, /* struct IntuiText *NextText */
X };
Xstruct IntuiText ab_txt2= {
X 3,2, /* FrontPen, BackPen */
X JAM1, /* DrawMode */
X centerX(32),35, /* LeftEdge, TopEdge */
X &font, /* TextAttr *ITextFont */
X (UBYTE *) "The Disk Magazine for the Amiga.", /* IText */
X &ab_txt3, /* struct IntuiText *NextText */
X };
Xstruct IntuiText ab_txt1= {
X 3,2, /* FrontPen, BackPen */
X JAM1, /* DrawMode */
X centerX(30),25, /* LeftEdge, TopEdge */
X &font, /* TextAttr *ITextFont */
X (UBYTE *) "First distributed on JUMPDISK,", /* IText */
X &ab_txt2, /* struct IntuiText *NextText */
X };
Xstruct IntuiText ab_txt0= {
X 3,2, /* FrontPen, BackPen */
X JAM1, /* DrawMode */
X centerX(33),15, /* LeftEdge, TopEdge */
X &font, /* TextAttr *ITextFont */
X (UBYTE *) "Copyright (c) 1988, Todd M. Lewis", /* IText */
X &ab_txt1, /* struct IntuiText *NextText */
X };
Xstruct IntuiText firsttext = {
X 3,2, /* FrontPen, BackPen */
X JAM1, /* DrawMode */
X centerX(27),6, /* LeftEdge, TopEdge */
X &font, /* TextAttr *ITextFont */
X (UBYTE *) "TML's AmigaMaze version 1.2", /* IText */
X &ab_txt0, /* struct IntuiText *NextText */
X };
X
Xstruct Requester aboutreq;
X
Xabout()
X{ struct IntuiMessage *msg;
X int class;
X
X InitRequester( &aboutreq );
X
X aboutreq.LeftEdge = 4;
X aboutreq.TopEdge = 15;
X aboutreq.Width = reqW;
X aboutreq.Height = reqH;
X aboutreq.ReqGadget = &aboutgad;
X aboutreq.ReqText = &firsttext;
X aboutreq.ReqBorder = &reqborder;
X aboutreq.BackFill = 2; /* BLACK */
X
X if (Request( &aboutreq, window )) {
X do {
X Wait( 1L << window->UserPort->mp_SigBit );
X while (msg = (struct IntuiMessage *)GetMsg( window->UserPort )) {
X class = msg->Class;
X ReplyMsg(msg);
X }
X } while ( class != REQCLEAR );
X }
X }
X
SHAR_EOF
echo "extracting maze.c"
sed 's/^X//' << \SHAR_EOF > maze.c
X#include <exec/types.h>
X#include <intuition/intuition.h>
X#include <functions.h>
X#include <graphics/gfxmacros.h>
X#include <graphics/text.h>
Xstruct IntuitionBase *IntuitionBase;
Xstruct GfxBase *GfxBase;
X
Xstruct RastPort tmpRPactual;
Xstruct RastPort *tmpRP = &tmpRPactual;
Xstruct BitMap tmpBM;
X
Xstruct TextAttr font = {
X (STRPTR)"topaz.font", /* Font Name */
X TOPAZ_EIGHTY, /* Font Height */
X FS_NORMAL, /* Font Style */
X FPF_ROMFONT /* Preferences */
X };
X
X#define tmpBMxy 60L
X
X#define windowW 552L
X#define windowH 183L
X
Xstruct NewWindow nw = {
X 6, 12, windowW, windowH, /* EDGES, SIZE */
X 0, 1, /* PENS */
X CLOSEWINDOW, /* IDCMPFlags */
X WINDOWDRAG | WINDOWDEPTH | /* Flags (requested window features)*/
X WINDOWCLOSE | ACTIVATE | REPORTMOUSE,
X NULL, /* gadgets */
X NULL, /* checkmark image */
X NULL, /* title */
X NULL, /* screen */
X NULL, /* bitmap */
X 0,0,0,0, /* min and max w and h */
X WBENCHSCREEN, /* TYPE */
X };
X
X
Xstruct IntuiText it_GiveUp = {
X 0,1, /* frontpen, backpen */
X JAM1, /* drawmode */
X 1,1, /* leftedge, topedge */
X &font, /* TextAttr * ITextFont */
X (UBYTE *)" Give Up! ", /* IText */
X NULL, /* NextText */
X };
Xstruct MenuItem mi_GiveUp = {
X (struct MenuItem *) NULL,
X 0,40, /* LeftEdge, TopEdge */
X 21*9,10, /* Width, Height */
X ITEMTEXT | HIGHCOMP | ITEMENABLED, /* Flags */
X 0, /* Mutual Exclude */
X (APTR)&it_GiveUp, /* ItemFill */
X NULL, /* SelectFill */
X 0, /* Command */
X NULL, /* Subitem */
X 0, /* NextSelect */
X };
X
Xstruct IntuiText it_3Level = {
X 0,1, /* frontpen, backpen */
X JAM1, /* drawmode */
X 1,1, /* leftedge, topedge */
X &font, /* TextAttr * ITextFont */
X (UBYTE *)"New 3-Level Maze", /* IText */
X NULL, /* NextText */
X };
Xstruct MenuItem mi_3Level = {
X (struct MenuItem *) &mi_GiveUp,
X 0,30, /* LeftEdge, TopEdge */
X 21*9,10, /* Width, Height */
X ITEMTEXT | HIGHCOMP | ITEMENABLED, /* Flags */
X 0, /* Mutual Exclude */
X (APTR)&it_3Level, /* ItemFill */
X NULL, /* SelectFill */
X 0, /* Command */
X NULL, /* Subitem */
X 0, /* NextSelect */
X };
X
Xstruct IntuiText it_2Level = {
X 0,1, /* frontpen, backpen */
X JAM1, /* drawmode */
X 1,1, /* leftedge, topedge */
X &font, /* TextAttr * ITextFont */
X (UBYTE *)"New 2-Level Maze", /* IText */
X NULL, /* NextText */
X };
Xstruct MenuItem mi_2Level = {
X (struct MenuItem *) &mi_3Level,
X 0,20, /* LeftEdge, TopEdge */
X 21*9,10, /* Width, Height */
X ITEMTEXT | HIGHCOMP | ITEMENABLED, /* Flags */
X 0, /* Mutual Exclude */
X (APTR)&it_2Level, /* ItemFill */
X NULL, /* SelectFill */
X 0, /* Command */
X NULL, /* Subitem */
X 0, /* NextSelect */
X };
Xstruct IntuiText it_1Level = {
X 0,1, /* frontpen, backpen */
X JAM1, /* drawmode */
X 1,1, /* leftedge, topedge */
X &font, /* TextAttr * ITextFont */
X (UBYTE *)"New 1-Level Maze", /* IText */
X NULL, /* NextText */
X };
Xstruct MenuItem mi_1Level = {
X (struct MenuItem *)&mi_2Level,
X 0,10, /* LeftEdge, TopEdge */
X 21*9,10, /* Width, Height */
X ITEMTEXT | HIGHCOMP | ITEMENABLED, /* Flags */
X 0, /* Mutual Exclude */
X (APTR)&it_1Level, /* ItemFill */
X NULL, /* SelectFill */
X 0, /* Command */
X NULL, /* Subitem */
X 0, /* NextSelect */
X };
X
Xstruct IntuiText it_About = {
X 0,1, /* frontpen, backpen */
X JAM1, /* drawmode */
X 1,1, /* leftedge, topedge */
X &font, /* TextAttr * ITextFont */
X (UBYTE *)"About TML's AmigaMaze", /* IText */
X NULL, /* NextText */
X };
Xstruct MenuItem mi_About = {
X (struct MenuItem *) &mi_1Level,
X 0,0, /* LeftEdge, TopEdge */
X 21*9,10, /* Width, Height */
X ITEMTEXT | HIGHCOMP | ITEMENABLED, /* Flags */
X 0, /* Mutual Exclude */
X (APTR)&it_About, /* ItemFill */
X NULL, /* SelectFill */
X 0, /* Command */
X NULL, /* Subitem */
X 0, /* NextSelect */
X };
Xstruct Menu menu = {
X (struct Menu *) NULL, /* NEXT menu */
X 0, 0, 12*9, 0, /* LeftEdge, TopEdge, Width, Height */
X MENUENABLED, /* Flags */
X (BYTE *) "Maze Control", /* MenuName */
X (struct MenuItem *)&mi_About, /* First item */
X 0,0,0,0, /* JazzX,JazzY, BeatX, BeatY */
X };
X
Xstruct Window *window;
X
X/* BEWARE: NOWHERE has a dual nature, being used as a doesn't-go-anywhere
X indicator, and also as an invalid level marker!!! */
X#define NOWHERE -1
X#define SOUTH 0
X#define EAST 1
X#define WEST 2
X#define NORTH 3
X
X#define SOLVED -3
X
X#define DIRECTIONS 4
X#define MAXLEVELS 3
X#define BOARDMAXX 36
X#define BOARDMAXY 29
X/*** the following are "inpath" stata. (see struct square) *******/
X#define NOTTRAVERSED 1
X#define EDGE 2
X#define LASTPIECE 3 + 32
X#define FIRSTPIECE 3 + 64
X#define CURPIECE 3 + 96
X#define TRAVERSED 3
X
X#define MIDCMP1 CLOSEWINDOW|MOUSEMOVE|MOUSEBUTTONS|MENUPICK|MENUVERIFY
X#define MIDCMP2 REQCLEAR
X#define MIDCMP3 CLOSEWINDOW
X
Xextern ULONG RangeRand();
Xextern int about();
Xextern int cycle();
X
Xtypedef struct {
X int conlev[ DIRECTIONS ]; /** level connected to in each dir. **/
X int inpath; /** Also the color this should be drawn in. **/
X int compass; /** Which direction to go to get home from here **/
X } square;
X
Xtypedef square BOARD[ BOARDMAXX+1 ][ BOARDMAXY+1 ][ MAXLEVELS ];
X
XBOARD board;
X
Xstruct RastPort *rp;
X
Xint StartX, StartY, StartLevel;
Xint EndX, EndY, EndLevel;
X
Xint CurX, CurY, CurLevel;
Xint NewX, NewY, NewLevel;
Xint MouseX, MouseY;
Xint MinLevel, MaxLevel;
Xint BoardMaxX = BOARDMAXX;
Xint BoardMaxY = BOARDMAXY;
Xint SquareXsize = 34;
Xint SquareYsize = 18;
X
X/* We need to have some Fill patterns for various places. Here goes... */
XUSHORT Pat_Normal[] = { /** the normal filled pattern **/
X 0xffff, /* plane 1 pattern */
X 0xffff,
X 0xffff, /* plane 2 pattern */
X 0xffff };
X
XUSHORT Pat_P1[] = { /** first dithered filled pattern **/
X 0x5555, /* plane 1 pattern */
X 0xaaaa,
X 0xffff, /* plane 2 pattern */
X 0xffff };
X
XUSHORT Pat_P2[] = { /** second dithered filled pattern **/
X 0xffff, /* plane 1 pattern */
X 0xffff,
X 0x5555, /* plane 2 pattern */
X 0xaaaa };
X
XsetHint(ShowHint)
Xint ShowHint;
X{
X char *s;
X int oldBPen;
X
X if (ShowHint) {
X switch ( board[CurX][CurY][CurLevel].compass) {
X case NORTH : s = " HINT: Go North! "; break;
X case SOUTH : s = " HINT: Go South! "; break;
X case EAST : s = " HINT: Go East! "; break;
X case WEST : s = " HINT: Go West! "; break;
X case SOLVED: s = " CONGRATULATIONS! "; break;
X default : s = " Hmm. I don't know. "; break;
X }
X }
X else {
X s = " (Press Left Button for a hint.)";
X }
X Move(rp, 20L, 180L);
X SetAPen(rp, 1L);
X oldBPen = rp -> BgPen;
X SetBPen(rp, 0L);
X SetDrMd(rp, (LONG)JAM2);
X Text(rp, s, 32L);
X SetBPen(rp, (LONG)oldBPen);
X }
X
Xshowside(ax,ay, bx,by, cx,cy, dx,dy, color)
XLONG ax,ay, bx,by, cx,cy, dx,dy, color;
X{
X SetAPen( tmpRP, color); /* The shape isn't allways a rect., so */
X SetOPen( tmpRP, color); /* we can't use RectFill() here... */
X BNDRYOFF( tmpRP); /* Boundaries look bad w/ patterns...*/
X switch (color) {
X case CURPIECE :
X case TRAVERSED : SetAfPt( tmpRP, Pat_P2,-1L); break;
X case LASTPIECE : SetAfPt( tmpRP, Pat_P1,-1L); break;
X case NOTTRAVERSED :
X case FIRSTPIECE :
X default : SetAfPt( tmpRP, Pat_Normal,-1L); break;
X }
X
X AreaMove( tmpRP, ax,ay);
X AreaDraw( tmpRP, bx,by);
X AreaDraw( tmpRP, cx,cy);
X AreaDraw( tmpRP, dx,dy);
X AreaEnd( tmpRP);
X SetAPen( tmpRP, (LONG)EDGE);
X Move( tmpRP, ax, ay);
X Draw( tmpRP, bx, by);
X Draw( tmpRP, bx+1,by);
X Draw( tmpRP, ax+1,ay);
X Move( tmpRP, cx, cy);
X Draw( tmpRP, dx, dy);
X Draw( tmpRP, dx+1,dy);
X Draw( tmpRP, cx+1,cy);
X }
X
Xputedge(ax,ay,bx,by)
XLONG ax,ay,bx,by;
X{
X SetAPen(tmpRP,(LONG)EDGE);
X Move(tmpRP,ax, ay);
X Draw(tmpRP,bx, by);
X Draw(tmpRP,bx+1,by);
X Draw(tmpRP,ax+1,ay);
X }
X
XLONG renderColor(x, y, z, x1, y1, z1)
Xint x, y, z, x1, y1, z1;
X{ int color;
X color = board[x][y][z].inpath;
X if (!(z == MaxLevel-1 && (color == FIRSTPIECE || color == LASTPIECE)))
X if ((color == NOTTRAVERSED) ||
X (board[x1][y1][z1].inpath == NOTTRAVERSED))
X color = NOTTRAVERSED;
X return((LONG)color);
X }
X
X#define XDIF 6
X#define YDIF 3
X
Xrender(x,y)
Xint x, y;
X{
X LONG ax,ay, bx,by, cx,cy, dx,dy, color;
X int level, Bleft, Btop, deltaX, deltaY, tmpL;
X int left, right, bottom, top;
X
X /* clear the temporary bitmap */
X SetAPen( tmpRP, 0L);
X SetBPen( tmpRP, 0L);
X RectFill( tmpRP, 0L, 0L, (LONG)SquareXsize, (LONG)SquareYsize );
X
X Bleft = 4 + (x - 1) * SquareXsize;
X Btop = 11 + (y - 1) * SquareYsize;
X
X left = 0;
X right = SquareXsize - 1;
X top = 0;
X bottom = SquareYsize - 1;
X
X for (level=MinLevel; level<MaxLevel; level++) {
X if (references(x, y, level) == 0)
X continue; /* This level doesn't go anywhere. */
X
X deltaY = YDIF * level + 1;
X deltaX = XDIF * level + 1;
X
X /**** Fill in the middle part first ****/
X ax = right - deltaX; ay = top + deltaY;
X bx = left + deltaX; by = ay;
X cx = bx; cy = bottom - deltaY;
X dx = ax; dy = cy;
X color = board[x][y][level].inpath;
X showside(ax,ay,bx,by,cx,cy,dx,dy,color);
X
X /**** Do the NORTH side of this level first ****/
X ax = right-deltaX; ay = top + deltaY;
X bx = ax; by = top;
X cx = left +deltaX; cy = by;
X dx = cx; dy = ay;
X tmpL = board[x][y][level].conlev[NORTH];
X if ( tmpL == NOWHERE) {
X putedge(ax,ay,dx,dy);
X goto DrawWest;
X }
X color = renderColor(x,y,level,x,y-1,tmpL);
X if (tmpL != level && level == 1) {
X bx = bx - XDIF*(tmpL - 1);
X cx = cx + XDIF*(tmpL - 1);
X }
X showside(ax,ay,bx,by,cx,cy,dx,dy,color);
X
X /**** Do the WEST side of this level next ****/
X DrawWest:
X ax = left + deltaX; ay = top + deltaY;
X bx = left; by = ay;
X cx = bx; cy = bottom - deltaY;
X dx = ax; dy = cy;
X tmpL = board[x][y][level].conlev[WEST];
X if ( tmpL == NOWHERE) {
X putedge(ax,ay,dx,dy);
X goto DrawSouth;
X }
X color = renderColor(x,y,level,x-1,y,tmpL);
X if (tmpL != level && level == 1) {
X by = by + YDIF*(tmpL - 1);
X cy = cy - YDIF*(tmpL - 1);
X }
X showside(ax,ay,bx,by,cx,cy,dx,dy,color);
X
X /**** Do the SOUTH side of this level next ****/
X DrawSouth:
X ax = left + deltaX; ay = bottom - deltaY;
X bx = ax; by = bottom;
X cx = right - deltaX; cy = by;
X dx = cx; dy = ay;
X tmpL = board[x][y][level].conlev[SOUTH];
X if ( tmpL == NOWHERE) {
X putedge(ax,ay,dx,dy);
X goto DrawEast;
X }
X color = renderColor(x,y,level,x,y+1,tmpL);
X if (tmpL != level && level == 1) {
X bx = bx + XDIF*(tmpL-1);
X cx = cx - XDIF*(tmpL-1);
X }
X showside(ax,ay,bx,by,cx,cy,dx,dy,color);
X
X /**** Do the EAST side of this level last ****/
X DrawEast:
X ax = right - deltaX; ay = bottom - deltaY;
X bx = right; by = ay;
X cx = bx; cy = top + deltaY;
X dx = ax; dy = cy;
X tmpL = board[x][y][level].conlev[EAST];
X if ( tmpL == NOWHERE) {
X putedge(ax,ay,dx,dy);
X goto DrawComplete;
X }
X color = renderColor(x,y,level,x+1,y,tmpL);
X if (tmpL != level && level == 1) {
X by = by - YDIF*(tmpL - 1);
X cy = cy + YDIF*(tmpL - 1);
X }
X showside(ax,ay,bx,by,cx,cy,dx,dy,color);
X DrawComplete:;
X }
X /* now copy temporary bitmap into window */
X
X BltBitMapRastPort(&tmpBM,0L,0L, rp,(LONG)Bleft,(LONG)Btop,
X (LONG)SquareXsize,(LONG)SquareYsize, (LONG)0x0c0);
X } /* end of render() */
X
X
X/* references() returns the number connections from a given square. */
Xint references(x, y, level)
Xint x, y, level;
X{ int i, refs;
X refs = 0;
X for (i=0; i < DIRECTIONS; i++)
X if (board[x][y][level].conlev[i] != NOWHERE)
X refs++;
X return(refs);
X }
X
X/* linkable() returns true if we can connect the two indicated squares. */
X/* NOTE: We don't allow connecting to the second square if it */
X/* is already part of the maze. This test if the first if stmt.*/
X/* The second test if more subtle. The problem being tested for is shown in */
X/* the following diagram. This is an edge-on view of the board: */
X/* a __ __ d */
X/* \ / */
X/* / */
X/* / */
X/* c __/ \__ b */
X/* If c and d are connected, I can't connect a to b because the paths would */
X/* intersect. The way the test is written, it will work regardless of whether */
X/* the new path is going up, down, or level. */
X
Xint linkable(x1,y1,level1,dir1, x2,y2, level2, dir2)
Xint x1,y1,level1,dir1, x2,y2,level2;
X{
X int tmp;
X if (references(x2,y2,level2)) return(0);
X if (board[x1][y1][level2].conlev[dir1] == level1) return(0);
X return(-1);
X }
X
X/* Returns the other Direction, or NOWHERE if an invalid direction is passed. */
Xint otherDir(nd)
Xint nd;
X{ switch (nd) {
X case NORTH : return(SOUTH); break;
X case SOUTH : return(NORTH); break;
X case EAST : return(WEST) ; break;
X case WEST : return(EAST) ; break;
X }
X return(NOWHERE);
X }
X
X
X/* makepathlist() returns the number of directions we can go from here w/o */
X/* backtracking -- i.e., not counting the way we got here. These */
X/* "uncharted" routes are characterized by .compus==NOWHERE. The list of */
X/* directions is placed in pl[]. */
X
Xint makepathlist(x,y,z,pl)
Xint x, y, z, pl[];
X{ int di, le, paths;
X paths = 0;
X for (di=0; di<DIRECTIONS; di++) {
X pl[paths] = di;
X le = board[x][y][z].conlev[di];
X if (le != NOWHERE)
X switch (di) {
X case NORTH : if (board[x][y-1][le].compass == NOWHERE)
X paths++;
X break;
X case SOUTH : if (board[x][y+1][le].compass == NOWHERE)
X paths++;
X break;
X case EAST : if (board[x+1][y][le].compass == NOWHERE)
X paths++;
X break;
X case WEST : if (board[x-1][y][le].compass == NOWHERE)
X paths++;
X break;
X case NOWHERE : break;
X }
X }
X return(paths);
X }
X
Xint topscore;
X
X/* buildreturnmap() is a recursive routine which starts the end of a path on */
X/* our tree-structured maze and traverses up to an intersection or dead end. */
X/* When we hit a dead end, we just return, but when we hit an intersection, we */
X/* call buildreturnmap() again, once for each path going off from the */
X/* intersection, except for the one got there on. We keep a score for how far */
X/* we are from the first square. One point per square, plus 5 times the */
X/* number of paths leading off from each intersection. We keep a topscore to */
X/* find out which square is farthest (in this modified sense) from our */
X/* starting square. This helps to ensure that we get a reasonably difficult */
X/* maze to solve. */
X/* We also record the direction to the end of the maze in each square. This */
X/* information is used by the hint facility. */
X
Xbuildreturnmap(x,y,z,score)
Xint x, y, z, score;
X{ int pathlist[DIRECTIONS], paths, i, le;
X
X while ( (paths = makepathlist(x,y,z,pathlist)) == 1) {
X z = board[x][y][z].conlev[pathlist[0]];
X switch (pathlist[0]) {
X case NORTH : y--; break;
X case SOUTH : y++; break;
X case EAST : x++; break;
X case WEST : x--; break;
X }
X board[x][y][z].compass = otherDir(pathlist[0]);
X /* score++; */
X }
X
X if (paths == 0) { /* We are at the end of a path... */
X if (score >= topscore) {
X topscore = score;
X StartX = x;
X StartY = y;
X StartLevel = z;
X }
X return;
X }
X
X /* if we got here, we are not at the end of a path. paths > 1 */
X score = score + paths;
X
X for (i=0; i<paths; i++) {
X le = board[x][y][z].conlev[pathlist[i]];
X switch (pathlist[i]) {
X case NORTH : board[x][y-1][le].compass = SOUTH;
X buildreturnmap(x,y-1,le,score); break;
X
X case SOUTH : board[x][y+1][le].compass = NORTH;
X buildreturnmap(x,y+1,le,score); break;
X
X case EAST : board[x+1][y][le].compass = WEST;
X buildreturnmap(x+1,y,le,score); break;
X
X case WEST : board[x-1][y][le].compass = EAST;
X buildreturnmap(x-1,y,le,score); break;
X }
X }
X }
X
X#define MAXENDS 120
X#define FREEEND -1
X#define LASTEND -1
Xtypedef struct {
X int x,y,z; /* board coordinates. x=FREEEND means this one is free */
X int prevdir; /* The direction we went to get here. */
X /* In picking what direction to go, we are biased */
X /* toward this direction. This gives paths */
X /* with several straight sections -- keeps one path from */
X /* knotting up one part of the board. */
X int nextfree; /* next unused end, LASTEND means no more */
X } endtype;
X
Xendtype ends[MAXENDS];
Xint firstfree;
Xint MaxEnds = MAXENDS;
X
Xinitends()
X{ int i;
X
X for (i=0; i<MaxEnds; i++) {
X ends[i].x = -1;
X ends[i].y = -1;
X ends[i].z = -1;
X ends[i].nextfree = i - 1;
X }
X firstfree = MaxEnds - 1;
X /* NOTE that ends[0].nextfree == -1 == LASTEND. If that define ever */
X /* changes, we will have to include the statement: */
X /* ends[0].nextfree = LASTEND; */
X }
X
X/* IF you want to play around with the parameters that effect the way
X boards are built, you will want to try different combinations of
X "tries", "length", and global MaxEnds. */
X
Xint extendend(curend,tries,length)
Xint curend, tries, length;
X{
X int x, y, level;
X int nd,od, nx, ny, nl, i, moves, link;
X
X moves = 0;
X
X x = ends[curend].x;
X y = ends[curend].y;
X level = ends[curend].z;
X nd = ends[curend].prevdir;
X
X /* try up to i times to add a random square */
X for (i=0; i<tries && moves < length; i++) {
X do { /* try not to go out of bounds */
X nd = ((RangeRand(10L) < 4) ? (int)RangeRand((LONG)DIRECTIONS) : nd);
X } while ((nd == NORTH && y == 1) ||
X (nd == WEST && x == 1) ||
X (nd == SOUTH && y == BoardMaxY-1) ||
X (nd == EAST && x == BoardMaxX-1) );
X /* Now that we've got a direction, see that we don't already go that way */
X if (board[x][y][level].conlev[nd] != NOWHERE)
X continue;
X nx = x; ny = y;
X switch (nd) { /* work out the new x and y */
X case NORTH : ny = y - 1; break;
X case SOUTH : ny = y + 1; break;
X case EAST : nx = x + 1; break;
X case WEST : nx = x - 1; break;
X }
X od = otherDir(nd);
X nl = level;
X
X /** get some level we can go onto from here **/
X if (!(link=linkable(x, y, level, nd, nx, ny, nl, od))) { /* stay on the same level if we can... */
X if (level > MinLevel) { /* can't stay on this level so go down */
X nl = level - 1;
X link = linkable(x, y, level, nd, nx, ny, nl, od); /* if we can't go down, go up */
X }
X if (!link && (level < MaxLevel - 1)) {
X nl = level + 1; /* can't go down or level, so try up */
X link = linkable(x, y, level, nd, nx, ny, nl, od);
X }
X }
X
X if (link) {
X board[x ][y ][level].conlev[nd] = nl;
X board[nx][ny][nl ].conlev[od] = level;
X render( x, y);
X render(nx,ny);
X moves++;
X /* sometimes fork, putting our old coordinates in a free end slot. */
X if (firstfree != LASTEND) { /* make sure there IS a free end slot */
X if (RangeRand(10L) < 4) {
X ends[firstfree].x = x;
X ends[firstfree].y = y;
X ends[firstfree].z = level;
X ends[firstfree].prevdir = nd;
X firstfree = ends[firstfree].nextfree;
X }
X }
X ends[curend].x = x = nx;
X ends[curend].y = y = ny;
X ends[curend].z = level = nl;
X }
X }
X /* if we got this far and made no moves, we are probably on dead end and */
X /* should put this ends[] on the free list. */
X if (moves == 0) {
X ends[curend].x = FREEEND;
X ends[curend].nextfree = firstfree;
X firstfree = curend;
X }
X return(moves);
X }
Xint xties, xlength;
Xint makepath()
X{ int i, endsfound, totalsquares;
X
X initends(); /* This sets the table of path ends to all zeros */
X
X /* ends[] is a list of the ends of paths which we can add more paths */
X /* onto. Note that they don't really have to be an end; they can be */
X /* in the middle of a path as well. Not all of them are in use as */
X /* an end all the time. Some are in a linked list of "free" ends, */
X /* available for use if we want to add an end. Free (unused) array */
X /* elements are marked by a .x == FREEEND. Ends get taken out of active */
X /* service and put on the free list when the path generator "extendend()" */
X /* fails to extend the path from that end. When no active ends remain, */
X /* maze generation terminates. */
X
X /* p.s.: I don't particularly care for the mazes that are generated by */
X /* this method, nor am I particularly fond of the method. I would like */
X /* to hear of other strategies for maze generation. */
X
X
X ends[firstfree].x = 1 + RangeRand((LONG)BoardMaxX - 1);
X ends[firstfree].y = 1 + RangeRand((LONG)BoardMaxY - 1);
X ends[firstfree].z = 0;
X ends[firstfree].prevdir = RangeRand((LONG)DIRECTIONS);
X firstfree = ends[firstfree].nextfree;
X
X totalsquares = 0;
X do {
X endsfound = 0;
X for (i=0; i< MaxEnds; i++) {
X if (ends[i].x != FREEEND) {
X endsfound++;
X totalsquares += extendend(i,xties,xlength);
X }
X }
X } while (endsfound);
X return( totalsquares );
X }
X
Xpickends()
X{ int x, y, z, i;
X
X /* Find then end of a path on the bottom level. */
X do {
X StartX = 1 + RangeRand( (LONG) BoardMaxX-1L );
X StartY = 1 + RangeRand( (LONG) BoardMaxY-1L );
X StartLevel = MinLevel;
X } while (references( StartX, StartY, StartLevel) != 1);
X
X /* The reason for doing this 4 times is to make the ends as far apart as */
X /* possible. If our first choice is close to the top of the tree, it */
X /* can't be very far away from every leaf node. The way this works is: */
X /* 1 Find a leaf node. */
X /* 2 Find the leaf farthest from the one found in step 1. */
X /* 3 Find the leaf farthest from the one found in step 2. ... */
X /* Eventually you should end up with two good choices for the ends. */
X
X for (i=0; i<4; i++) {
X for (x=1; x<BoardMaxX; x++)
X for (y=1; y<BoardMaxY; y++)
X for (z=MinLevel; z<MaxLevel; z++)
X board[x][y][z].compass = NOWHERE;
X
X EndX = StartX; EndY = StartY; EndLevel = StartLevel;
X board[ EndX ][ EndY ][ EndLevel ].compass = SOLVED;
X topscore = 0;
X buildreturnmap(EndX, EndY, EndLevel, 0);
X }
X
X board[ StartX ][ StartY ][ StartLevel ].inpath = FIRSTPIECE;
X board[ EndX ][ EndY ][ EndLevel ].inpath = LASTPIECE;
X CurX = StartX;
X CurY = StartY;
X CurLevel = StartLevel;
X NewX = CurX;
X NewY = CurY;
X NewLevel = CurLevel;
X render( StartX, StartY);
X render( EndX, EndY);
X }
X
Xinit1( l )
Xint l;
X{
X int i, x, y, level, dir;
X static int Xsize[] = { 54, 16, 24, 34 }; /* Square widths */
X static int Xsqrs[] = { 10, 34, 22, 16 }; /* No. of squares */
X
X static int Ysize[] = { 26, 10, 14, 18 }; /* Square heights */
X static int Ysqrs[] = { 6, 16, 11, 9 }; /* No. of squares */
X
X /* Reset the entire board, including a strip of squares around */
X /* the edges that we never go into. */
X for(x=0; x <= BOARDMAXX; x++)
X for(y=0; y <= BOARDMAXY; y++)
X for(level=0; level < MAXLEVELS; level++) {
X board[x][y][level].inpath = NOTTRAVERSED;
X board[x][y][level].compass = NOWHERE;
X for(dir=0; dir < DIRECTIONS; dir++)
X board[x][y][level].conlev[dir] = NOWHERE;
X }
X
X SetAPen( rp, 0L);
X SetBPen( rp, 0L);
X RectFill( rp, 4L, 11L, (LONG)windowW-4, (LONG)windowH-2);
X
X MaxLevel = l; /* l==0 is a special-case first-time super-easy 1-level */
X /* maze. It generates fast so we can get to the menus. */
X
X BoardMaxX = Xsqrs[ MaxLevel ] + 1;
X SquareXsize = Xsize[ MaxLevel ];
X BoardMaxY = Ysqrs[ MaxLevel ] + 1;
X SquareYsize = Ysize[ MaxLevel ];
X
X if (MaxLevel == 0)
X MaxLevel = 1;
X
X makepath();
X
X pickends();
X setHint( (int)FALSE );
X }
X
Xint autosolve()
X{ int newDir;
X square *oldSq, *newSq;
X
X while ( (newDir = board[CurX][CurY][CurLevel].compass) != SOLVED ) {
X NewX = CurX;
X NewY = CurY;
X NewLevel = board[CurX][CurY][CurLevel].conlev[newDir];
X switch (newDir) {
X case NORTH : NewY--; break;
X case SOUTH : NewY++; break;
X case EAST : NewX++; break;
X case WEST : NewX--; break;
X }
X
X oldSq = &board[ CurX ][ CurY ][ CurLevel];
X newSq = &board[ NewX ][ NewY ][ NewLevel];
X
X oldSq->inpath = TRAVERSED;
X
X switch (newSq->inpath) {
X case TRAVERSED :
X case FIRSTPIECE : /* We must have backed up to get here, so...*/
X oldSq->inpath = NOTTRAVERSED; break;
X default : ;
X }
X
X /* set the inpath flag of the new square in any case */
X newSq->inpath = CURPIECE;
X
X /* Also, just in case we backed up to the starting square */
X /* or from the ending square.... */
X board[StartX][StartY][StartLevel].inpath = FIRSTPIECE;
X board[EndX ][EndY ][EndLevel ].inpath = LASTPIECE;
X
X /* Now draw both squares */
X render(CurX,CurY);
X render(NewX,NewY);
X
X /* Now new becomes current */
X CurX = NewX;
X CurY = NewY;
X CurLevel = NewLevel;
X
X }
X }
X
X
X
Xint mousewatch()
X{ static int canmove = FALSE;
X int x, y, newDir;
X
X x = ((MouseX) - 4)/SquareXsize + 1;
X y = ((MouseY) - 11)/SquareYsize + 1;
X
X x = x * SIGN(MouseX);
X y = y * SIGN(MouseY);
X
X if (x == CurX && y == CurY) {
X canmove = TRUE;
X }
X
X newDir = NOWHERE;
X if (x == CurX) {
X if (y == CurY + 1 && y < BoardMaxY)
X newDir = SOUTH;
X else if (y == CurY - 1 && y > 0)
X newDir = NORTH;
X }
X else
X if (y == CurY) {
X if (x == CurX + 1 && x < BoardMaxX)
X newDir = EAST;
X else if (x == CurX - 1 && x > 0)
X newDir = WEST;
X }
X
X if (newDir == NOWHERE ) {
X canmove = FALSE;
X return(NOWHERE);
X }
X
X NewLevel = board[CurX][CurY][CurLevel].conlev[newDir];
X
X if (NewLevel == NOWHERE) {
X canmove = FALSE;
X return(NOWHERE);
X }
X NewX = x;
X NewY = y;
X return(newDir);
X }
X
Xint trymove() /* returns TRUE if we won, FALSE if we didn't win. */
X{ int newDir;
X square *oldSq, *newSq;
X
X newDir = mousewatch();
X if (newDir == NOWHERE)
X return(board[CurX][CurY][CurLevel].compass == SOLVED);
X
X oldSq = &board[ CurX ][ CurY ][ CurLevel];
X newSq = &board[ NewX ][ NewY ][ NewLevel];
X
X oldSq->inpath = TRAVERSED;
X switch (newSq->inpath) {
X case TRAVERSED :
X case FIRSTPIECE : /* We must have backed up to get here, so...*/
X oldSq->inpath = NOTTRAVERSED; break;
X default : ;
X }
X
X /* set the inpath flag of the new square in any case */
X newSq->inpath = CURPIECE;
X
X /* Also, just in case we backed up from the starting square */
X /* or the ending square.... */
X board[StartX][StartY][StartLevel].inpath = FIRSTPIECE;
X board[EndX ][EndY ][EndLevel ].inpath = LASTPIECE;
X
X /* Now draw both squares */
X render(CurX,CurY);
X render(NewX,NewY);
X
X /* Now new becomes current */
X CurX = NewX;
X CurY = NewY;
X CurLevel = NewLevel;
X
X /* ?did we win? */
X
X setHint((int)(newSq->compass == SOLVED));
X
X if (newSq->compass == SOLVED) {
X cycle( 3 );
X return( (int)TRUE );
X }
X return( (int)FALSE);
X }
X
XHandleMenu(menucode)
XUSHORT menucode;
X{
X ModifyIDCMP( window, (ULONG) MIDCMP2 );
X
X switch ( ITEMNUM( menucode) ) {
X case 0 : about() ; break;
X case 1 : init1( 1 ); break;
X case 2 : init1( 2 ); break;
X case 3 : init1( 3 ); break;
X case 4 : autosolve(); break;
X }
X
X ModifyIDCMP( window, (ULONG) MIDCMP1 );
X }
X
X
XEventLoop()
X{
X struct IntuiMessage *mesg;
X ULONG class, code, mousemoved, closewindow, menupick;
X USHORT menucode;
X
X closewindow = FALSE;
X ModifyIDCMP( window, (ULONG) MIDCMP1 );
X
X do {
X mousemoved = FALSE;
X menupick = FALSE;
X
X Wait( (LONG) 1 << window -> UserPort -> mp_SigBit);
X
X while ((mesg=(struct IntuiMessage *)GetMsg(window->UserPort))) {
X class = mesg->Class;
X code = mesg->Code;
X MouseX = mesg->MouseX;
X MouseY = mesg->MouseY;
X ReplyMsg(mesg);
X if (class == MOUSEMOVE) mousemoved = TRUE;
X if (class == CLOSEWINDOW) closewindow = TRUE;
X if (class == MOUSEBUTTONS && code == SELECTDOWN)
X setHint( (int) TRUE);
X if (class == MENUPICK) {
X menupick = TRUE;
X menucode = code;
X }
X }
X if (mousemoved) trymove();
X if (menupick) HandleMenu(menucode);
X } while (closewindow == FALSE);
X }
X
Xstruct TextFont *textfont = NULL;
X
Xopenstuff()
X{ ULONG Seconds, Micros;
X
X IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0L);
X if (IntuitionBase == NULL) {closestuff(); exit(0);}
X
X GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L);
X if (GfxBase == NULL) {closestuff(); exit(0); }
X
X /* My <functions.h> shows OpenFont() returns a *Font. */
X /* I think that is an error! */
X
X textfont = (struct TextFont *)OpenFont( &font );
X if (textfont==NULL) { closestuff(); exit(0); }
X
X if (( window=(struct Window *)OpenWindow(&nw))==NULL) {
X closestuff();
X exit(0);
X }
X if (SetFont(window->RPort,textfont)==0) { closestuff(); exit(0); }
X
X SetWindowTitles(window,(UBYTE *)" TML's AmigaMaze ver. 1.2 ",
X (UBYTE *)"TML's AmigaMaze First distributed on JUMPDISK.");
X
X SetMenuStrip( window, &menu);
X
X /* This next bit is a cludge because I can't seem to get */
X /* extern ULONG RangeSeed; */
X /* to work. Anyone got any ideas? */
X /* LATER: It turns out that the RangeSeed is not public */
X /* in the Manx sources. Hope they fix this someday. */
X CurrentTime(&Seconds,&Micros);
X Micros = Micros & (ULONG) 0x0fff;
X for (Seconds=0; Seconds < Micros; Seconds++)
X RangeRand(4L);
X }
X
X
Xclosestuff()
X{ int i;
X for(i=0; i<2; i++) {
X if (tmpBM.Planes[i])
X FreeRaster(tmpBM.Planes[i],tmpBMxy,tmpBMxy);
X }
X if (window) {
X ClearMenuStrip( window );
X CloseWindow(window);
X }
X if (textfont) CloseFont(textfont);
X if (GfxBase) CloseLibrary(GfxBase);
X if (IntuitionBase) CloseLibrary(IntuitionBase);
X }
X
Xmain(/*argc,argv*/)
X/* int argc; */
X/* char *argv[]; */
X{ UWORD areabuffer[250], areabuffer2[250];
X struct TmpRas tmpras, tmprasB;
X struct AreaInfo areainfo, areainfo2;
X PLANEPTR plane,planeB;
X int i;
X
X /* if (argc > 1) */
X /* xties = atoi(argv[1]); */
X /* if (xties < 1 || xties > 100) */
X xties = 30;
X
X /* if (argc > 2) */
X /* xlength = atoi(argv[2]); */
X /* if (xlength < 1 || xlength > 100) */
X xlength = 9;
X
X /* if (argc > 3) */
X /* MaxEnds = atoi(argv[3]); */
X /* if (MaxEnds < 2 || MaxEnds > MAXENDS) */
X MaxEnds = MAXENDS;
X
X MaxLevel = 1;
X MinLevel = 0;
X openstuff();
X InitBitMap( &tmpBM, 2L, tmpBMxy, tmpBMxy );
X for (i=0; i<2; i++) {
X if ((tmpBM.Planes[i] = (PLANEPTR)AllocRaster(tmpBMxy,tmpBMxy))==NULL) {
X closestuff();
X exit(0);
X }
X }
X rp = window->RPort;
X if ((plane = AllocRaster(windowW,windowH))==NULL) {
X closestuff();
X exit(0);
X }
X if ((planeB = AllocRaster(tmpBMxy,tmpBMxy))==NULL) {
X FreeRaster(plane, windowW,windowH);
X closestuff();
X exit(0);
X }
X InitArea(&areainfo, areabuffer, 90L);
X InitArea(&areainfo2,areabuffer2,90L);
X
X InitTmpRas(&tmpras, plane, RASSIZE( windowW, windowH));
X InitTmpRas(&tmprasB,planeB,RASSIZE( tmpBMxy, tmpBMxy));
X
X rp->AreaInfo = &areainfo;
X rp->TmpRas = &tmpras;
X
X InitRastPort( tmpRP );
X if (SetFont(tmpRP,textfont)==0) { closestuff(); exit(0); }
X tmpRP->BitMap = &tmpBM;
X tmpRP->AreaInfo = &areainfo2;
X tmpRP->TmpRas = &tmprasB;
X
X init1(0); /* Zero is a special case. Super simple fast easy maze
X so the user can get to the menus w/o waiting so long. */
X ModifyIDCMP( window, (ULONG) MIDCMP2 );
X about();
X EventLoop();
X FreeRaster(plane, windowW, windowH);
X FreeRaster(planeB,tmpBMxy, tmpBMxy);
X closestuff();
X }
X
X/* Save some code space by stubbing _wb_parse() and _cli_parse(). */
Xvoid _wb_parse()
X{ }
X
Xvoid _cli_parse()
X{ }
X
SHAR_EOF
echo "extracting stdhead.c"
sed 's/^X//' << \SHAR_EOF > stdhead.c
X#include <exec/types.h>
X#include <intuition/intuition.h>
X#include <functions.h>
X#include <graphics/gfxmacros.h>
X#include <graphics/view.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
SHAR_EOF
echo "extracting makefile"
sed 's/^X//' << \SHAR_EOF > makefile
Xstdhead.t: stdhead.c
X cc +Hstdhead.t +m stdhead.c
X
Xabout.o: about.c stdhead.t
X cc -n +Istdhead.t about.c
X
Xmaze.o: maze.c stdhead.t
X cc -n +Istdhead.t maze.c
X
Xmaze: maze.o about.o
X ln -g maze.o about.o -lc
X
X# maze.l: maze.c about.c
X# lint >maze.l -iSYS1:include/ -zero -si2 SYS9:manx.c maze.c about.c
X
SHAR_EOF
echo "End of archive 1 (of 1)"
# if you want to concatenate archives, remove anything after this line
exit