
#include <exec/memory.h>
#include <exec/execbase.h>
#include <graphics/gfxbase.h>
#include <intuition/intuitionbase.h>
#include <dos/dosextens.h>
#include <libraries/iffparse.h>
#include <utility/tagitem.h>

#define __USE_SYSBASE 42

#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/utility.h>

#include <string.h>

#include "BTD.h"

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *UtilityBase;
struct DosLibrary *DOSBase;

#define MZTAG(o) (BTD_Client+(o))

#define MZ_CellSize   MZTAG(0)
#define MZ_SolveDelay MZTAG(1)
#define MZ_Colors     MZTAG(2)

#define DEF_CELLSIZE     7
#define DEF_SOLVEDELAY   3
#define DEF_COLORS       2

#define MIN_CELLSIZE     3
#define MIN_SOLVEDELAY   0
#define MIN_COLORS       2

#define MAX_CELLSIZE    25
#define MAX_SOLVEDELAY  15
#define MAX_COLORS     255

struct BTDInteger MazeIntParams[] =
 {
  MZ_CellSize,"Cell Size",BTDPT_INTEGER,DEF_CELLSIZE,MIN_CELLSIZE,MAX_CELLSIZE,TRUE,
  MZ_SolveDelay,"Solve Delay",BTDPT_INTEGER,DEF_SOLVEDELAY,MIN_SOLVEDELAY,MAX_SOLVEDELAY,TRUE,
  MZ_Colors,"Colors",BTDPT_INTEGER,DEF_COLORS,MIN_COLORS,MAX_COLORS,TRUE
 };

struct BTDNode *MazeParams[] =
 {
  &MazeIntParams[0].BI_Node,
  &MazeIntParams[1].BI_Node,
  &MazeIntParams[2].BI_Node,
  NULL
 };

struct BTDInfo MazeInfo =
 {
  BTDI_Revision,MAKE_ID('M','A','Z','E'),
  "Maze","Maze Blanker","Matthias Scheler",
  MazeParams
 };

/* blanker stuff */

typedef struct _Stack
 {
  LONG st_x;
  LONG st_y;
  BYTE st_DirOne;
  BYTE st_DirTwo;
  BYTE st_DirThree;
  BYTE st_DirFour;
  struct _Stack *st_Prev;
 } Stack;

typedef struct _Maze
 {
  struct BTDDrawInfo *mz_BTDDrawInfo;
  struct RastPort *mz_RPort;
  LONG mz_Left;
  LONG mz_Top;
  LONG mz_Width;
  LONG mz_Height;
  LONG mz_WidStep;
  LONG mz_HeiStep;
  BYTE *mz_Cells;
  BYTE *mz_LeftWalls;
  BYTE *mz_TopWalls;
  Stack *mz_Stack;
  LONG mz_RandN,mz_RandF,mz_RandI;
  LONG mz_StackLength,mz_SolutionLength,mz_NumCols,mz_FirstCol;
  LONG mz_Iter,mz_SolPeriod,mz_SolDelay;
  BYTE mz_Dirs[4];
  BOOL mz_SolveMode;
  Stack *mz_Cell;
  LONG mz_StartY,mz_SolutionY;
 } Maze;

#define NORTH 0
#define EAST  1
#define SOUTH 2
#define WEST  3

#define HasBeenVisited(Bob,x,y) ((Bob)->mz_Cells[(x)*(Bob)->mz_Height+(y)])
#define Visit(Bob,x,y)          ((Bob)->mz_Cells[(x)*(Bob)->mz_Height+(y)]=1)

LONG DirArray[] =
 {
  0x00010203L,0x00010302L,0x00020103L,0x00020301L,0x00030102L,0x00030201L,
  0x01000203L,0x01000302L,0x01020003L,0x01020300L,0x01030002L,0x01030200L,
  0x02000103L,0x02000301L,0x02010003L,0x02010300L,0x02030001L,0x02030100L,
  0x03000102L,0x03000201L,0x03010002L,0x03010200L,0x03020001L,0x03020100L
 };

/* rainbow colors */

#define NUM_RAINBOW_COLORS 6

UBYTE RBRed[NUM_RAINBOW_COLORS+1]   = {0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF};
UBYTE RBGreen[NUM_RAINBOW_COLORS+1] = {0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00};
UBYTE RBBlue[NUM_RAINBOW_COLORS+1]  = {0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00};

/* library stuff */

char MyBlankerName[] = "maze.btd";
char MyBlankerID[]   = "Maze Blanker V" VERSION "." REVISION " for BTD";

LONG MyBlankerLibInit(void)

{
 if (GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37L))
  {
   if (IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37L))
    {
     if (UtilityBase=OpenLibrary("utility.library",37L))
      {
       if (DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37L)) return TRUE;

       CloseLibrary (UtilityBase);
      }
     CloseLibrary (&IntuitionBase->LibNode);
    }
   CloseLibrary (&GfxBase->LibNode);
  }
 return FALSE;
}

void MyBlankerLibFree(void)

{
 CloseLibrary (&DOSBase->dl_lib);
 CloseLibrary (UtilityBase);
 CloseLibrary (&IntuitionBase->LibNode);
 CloseLibrary (&GfxBase->LibNode);
}

/* random generator */

void __regargs InitRandom(Maze *Bob,ULONG Instance)

{
 ULONG Time[2];

 CurrentTime (&Time[0],&Time[1]);
 Bob->mz_RandN=(LONG)Time[0];

 if (Time[1]<1024L) Time[1]|=1;
 else Time[1]>>=10;
 Time[1]^=Instance;

 Bob->mz_RandF=4*Time[1]+1;
 Bob->mz_RandI=2*Time[1]+1;
}

WORD __regargs Random(Maze *Bob,WORD Max)

{
 Bob->mz_RandN=Bob->mz_RandF*Bob->mz_RandN+Bob->mz_RandI;
 if (Bob->mz_RandN<0L) Bob->mz_RandN=-Bob->mz_RandN;

 return (WORD)(Bob->mz_RandN%Max);
}

/* stack handling */

Stack __regargs *AllocStack(LONG x,LONG y,BYTE *Directions)

{
 Stack *New;
  
 if (New=AllocVec(sizeof(Stack),MEMF_PUBLIC))
  {
   New->st_x=x;
   New->st_y=y;
   (void)memcpy(&New->st_DirOne,Directions,4*sizeof(BYTE));
   New->st_Prev=NULL;
  }
 return New;
}

#define Push(b,c) (b)->mz_StackLength++; (c)->st_Prev=(b)->mz_Stack; (b)->mz_Stack=(c)

Stack __regargs *Pop(Maze *Bob)

{
 Stack *Popped;
	
 if (Popped=Bob->mz_Stack)
  {
   Bob->mz_StackLength--;
   Bob->mz_Stack=Popped->st_Prev;
  }
 return Popped;
}

void __regargs FreeMaze(Maze *Bob)

{
 if (Bob->mz_Cells) FreeVec (Bob->mz_Cells);
 if (Bob->mz_LeftWalls) FreeVec (Bob->mz_LeftWalls);
 if (Bob->mz_TopWalls) FreeVec (Bob->mz_TopWalls);
 FreeVec (Bob);
}

/* maze handling */

Maze __regargs *AllocMaze(struct BTDDrawInfo *BTDDrawInfo,LONG Width,LONG Height)

{
 Maze *New;
  
 if (New=AllocVec(sizeof(Maze),MEMF_PUBLIC|MEMF_CLEAR))
  {
   New->mz_BTDDrawInfo=BTDDrawInfo;
   New->mz_RPort=BTDDrawInfo->BDI_RPort;
   New->mz_Left=BTDDrawInfo->BDI_Left;
   New->mz_Top=BTDDrawInfo->BDI_Top;
   New->mz_Width=Width;
   New->mz_Height=Height;
   New->mz_WidStep=(BTDDrawInfo->BDI_Width-1)/Width;
   New->mz_HeiStep=(BTDDrawInfo->BDI_Height-1)/Height;
   New->mz_Cells=AllocVec(sizeof(BYTE)*Width*Height,MEMF_PUBLIC|MEMF_CLEAR);
   New->mz_LeftWalls=AllocVec(sizeof(BYTE)*(Width+1)*Height,MEMF_PUBLIC|MEMF_CLEAR);
   New->mz_TopWalls=AllocVec(sizeof(BYTE)*Width*(Height+1),MEMF_PUBLIC|MEMF_CLEAR);
   
   if (New->mz_Cells&&New->mz_LeftWalls&&New->mz_TopWalls) return New;
   
   FreeMaze (New);
  }
 return NULL;
}

#define ActivateLeftWall(x,y) (Bob->mz_LeftWalls[(x)*Bob->mz_Height+(y)]=1)
#define ActivateTopWall(x,y)  (Bob->mz_TopWalls[(x)*Bob->mz_Height+(y)]=1)

#define LeftWallActive(x,y) (Bob->mz_LeftWalls[(x)*Bob->mz_Height+(y)])
#define TopWallActive(x,y)  (Bob->mz_TopWalls[(x)*Bob->mz_Height+(y)])

void __regargs AddHorizWall(Maze *Bob,LONG x,LONG y)

{
 Move (Bob->mz_RPort,Bob->mz_Left+x*Bob->mz_WidStep,Bob->mz_Top+y*Bob->mz_HeiStep);
 Draw (Bob->mz_RPort,Bob->mz_Left+(x+1)*Bob->mz_WidStep,Bob->mz_Top+y*Bob->mz_HeiStep);
}

void __regargs AddVertWall(Maze *Bob,LONG x,LONG y)

{
 Move (Bob->mz_RPort,Bob->mz_Left+x*Bob->mz_WidStep,Bob->mz_Top+y*Bob->mz_HeiStep);
 Draw (Bob->mz_RPort,Bob->mz_Left+x*Bob->mz_WidStep,Bob->mz_Top+(y+1)*Bob->mz_HeiStep);
}

void __regargs DrawSolution(Maze *Bob,LONG x,LONG y,LONG Pen,LONG Trailer)

{
 SetAPen (Bob->mz_RPort,Pen?Bob->mz_BTDDrawInfo->BDI_Pens[Pen-1]:BTD_BgPen);

 switch (Trailer)
  {
   case NORTH:
    RectFill (Bob->mz_RPort,
              Bob->mz_Left+x*Bob->mz_WidStep+1,
              Bob->mz_Top+y*Bob->mz_HeiStep+1,
              Bob->mz_Left+(x+1)*Bob->mz_WidStep-1,
              Bob->mz_Top+(y+1)*Bob->mz_HeiStep);
    break;
   case SOUTH:
    RectFill (Bob->mz_RPort,
              Bob->mz_Left+x*Bob->mz_WidStep+1,
              Bob->mz_Top+y*Bob->mz_HeiStep,
              Bob->mz_Left+(x+1)*Bob->mz_WidStep-1,
              Bob->mz_Top+(y+1)*Bob->mz_HeiStep-1);
    break;
   case EAST:
    RectFill (Bob->mz_RPort,
              Bob->mz_Left+x*Bob->mz_WidStep+1,
              Bob->mz_Top+y*Bob->mz_HeiStep+1,
              Bob->mz_Left+(x+1)*Bob->mz_WidStep,
              Bob->mz_Top+(y+1)*Bob->mz_HeiStep-1);
    break;
   case WEST:
    RectFill (Bob->mz_RPort,
              Bob->mz_Left+x*Bob->mz_WidStep,
              Bob->mz_Top+y*Bob->mz_HeiStep+1,
              Bob->mz_Left+(x+1)*Bob->mz_WidStep-1,
              Bob->mz_Top+(y+1)*Bob->mz_HeiStep-1);
  }

 if ((++Bob->mz_Iter%Bob->mz_SolPeriod)==0L) Delay (Bob->mz_SolDelay);
}

BYTE __regargs *RemoveDir(Maze *Bob,BYTE *Dir,BYTE RemMe)

{
 ULONG Index;
  
 for (Index=0L; Index<4L; Index++)
  Bob->mz_Dirs[Index]=(Dir[Index]==RemMe)?4:Dir[Index];
  
 return Bob->mz_Dirs;
}

#define DefRemDir(x) RemoveDir(Bob,(BYTE*)&DirArray[Random(Bob,24)],x)

Stack __regargs *GoDirection(Maze *Bob,Stack *Cell,BYTE DirNum)

{
 LONG x,y;
 BYTE Direction;

 x=Cell->st_x;
 y=Cell->st_y;

 switch (DirNum)
  {
   case 0:
    Direction=Cell->st_DirOne;
    Cell->st_DirOne=4;
    break;
   case 1:
    Direction=Cell->st_DirTwo;
    Cell->st_DirTwo=4;
    break;
   case 2:
    Direction=Cell->st_DirThree;
    Cell->st_DirThree=4;
    break;
   case 3:
    Direction=Cell->st_DirFour;
    Cell->st_DirFour=4;
   }
  
 switch( Direction )
  {
   case EAST:
    if (x<(Bob->mz_Width-1))
     if (!HasBeenVisited(Bob,x+1,y))
      {
       Push (Bob,Cell);
       return AllocStack(x+1,y,DefRemDir(WEST));
      }
     else
      {
       AddVertWall (Bob,x+1,y);
       ActivateLeftWall (x+1,y);
      }
    break;
   case NORTH:
    if (y<(Bob->mz_Height-1))
     if (!HasBeenVisited( Bob,x,y+1))
      {
       Push (Bob,Cell);
       return AllocStack(x,y+1,DefRemDir(SOUTH));
      }
     else
      {
       AddHorizWall (Bob,x,y+1);
       ActivateTopWall (x,y+1);
      }
    break;
   case WEST:
    if (x>0)
     if (!HasBeenVisited(Bob,x-1,y))
      {
       Push (Bob,Cell);
       return AllocStack(x-1,y,DefRemDir(EAST));
      }
     else
      {
       AddVertWall (Bob,x,y);
       ActivateLeftWall (x,y);
      }
    break;
   case SOUTH:
    if (y>0)
     if (!HasBeenVisited(Bob,x,y-1))
      {
       Push (Bob,Cell);
       return AllocStack(x,y-1,DefRemDir(NORTH));
      }
     else
      {
       AddHorizWall (Bob,x,y);
       ActivateTopWall (x,y);
      }
  }

 return NULL;
}

void __regargs ConstructMaze(Maze *Bob,LONG x,LONG y,LONG sx,LONG sy)

{
 Stack *Cell,*NewCell;
 
 if ((Cell=Bob->mz_Cell)==NULL) Cell=AllocStack(x,y,(BYTE *)&DirArray[Random(Bob,24)]);

 if ((Cell->st_x==sx)&&(Cell->st_y==sy)&&(Bob->mz_SolutionLength==0L))
  Bob->mz_SolutionLength=Bob->mz_StackLength;

 Visit (Bob,Cell->st_x,Cell->st_y);
    
 if (NewCell=GoDirection(Bob,Cell,0)) Cell=NewCell;
 else    
  if (NewCell=GoDirection(Bob,Cell,1)) Cell=NewCell;
  else    
   if (NewCell=GoDirection(Bob,Cell,2)) Cell=NewCell;
   else
    if (NewCell=GoDirection(Bob,Cell,3)) Cell=NewCell;
    else
     {    
      FreeVec (Cell);
      Cell=Pop(Bob);
     }

 Bob->mz_Cell=Cell;
}

Stack __regargs *SolveDirection(Maze *Bob,Stack *Cell,BYTE DirNum)

{
 LONG x,y,Pen;
 BYTE Direction;

 x=Cell->st_x;
 y=Cell->st_y;
 switch (DirNum)
  {
   case 0:
    Direction=Cell->st_DirOne;
    Cell->st_DirOne=4;
    break;
   case 1:
    Direction=Cell->st_DirTwo;
    Cell->st_DirTwo=4;
    break;
   case 2:
    Direction=Cell->st_DirThree;
    Cell->st_DirThree=4;
    break;
   case 3:
    Direction=Cell->st_DirFour;
    Cell->st_DirFour=4;
  }

 Pen=((Bob->mz_StackLength*Bob->mz_NumCols/Bob->mz_SolutionLength+Bob->mz_FirstCol)%Bob->mz_NumCols)+1L;
 switch (Direction)
  {
   case EAST:
    if (x<(Bob->mz_Width-1))
     if (!LeftWallActive(x+1,y))
      {
       Push (Bob,Cell);
       DrawSolution (Bob,x+1,y,Pen,WEST);
       return AllocStack(x+1,y,DefRemDir(WEST));
      }
    break;
   case NORTH:
    if (y<(Bob->mz_Height-1))
     if (!TopWallActive(x,y+1))
      {
       Push (Bob,Cell);
       DrawSolution (Bob,x,y+1,Pen,SOUTH);
       return AllocStack(x,y+1,DefRemDir(SOUTH));
      }
    break;
   case WEST:
    if (x>0)
     if (!LeftWallActive(x,y))
      {
       Push (Bob,Cell);
       DrawSolution (Bob,x-1,y,Pen,EAST);
       return AllocStack(x-1,y,DefRemDir(EAST));
      }
    break;
   case SOUTH:
    if (y>0)
     if (!TopWallActive(x,y))
      {
       Push (Bob,Cell);
       DrawSolution (Bob,x,y-1,Pen,NORTH);
       return AllocStack(x,y-1,DefRemDir(NORTH));
      }
  }

 return NULL;
}

void __regargs SolveMaze(Maze *Bob,LONG x,LONG y,LONG sx,LONG sy)

{
 Stack *Cell,*NewCell;

 if ((Cell=Bob->mz_Cell)==NULL) Cell=AllocStack(x,y,(BYTE *)&DirArray[Random(Bob,24)]);
  
 if ((Cell->st_x==sx)&&(Cell->st_y==sy))
  do FreeVec (Cell);
  while (Cell=Pop(Bob));
 else
  if (NewCell=SolveDirection(Bob,Cell,0)) Cell=NewCell;
  else    
   if (NewCell=SolveDirection(Bob,Cell,1)) Cell=NewCell;
   else    
    if (NewCell=SolveDirection(Bob,Cell,2)) Cell=NewCell;
    else    
     if (NewCell=SolveDirection(Bob,Cell,3)) Cell=NewCell;
     else
      {    
       x=Cell->st_x;
       y=Cell->st_y;

       FreeVec (Cell);
       Cell=Pop(Bob);

       if (Cell->st_x>x) DrawSolution (Bob,x,y,0,EAST);
       if (Cell->st_x<x) DrawSolution (Bob,x,y,0,WEST);
       if (Cell->st_y>y) DrawSolution (Bob,x,y,0,NORTH);
       if (Cell->st_y<y) DrawSolution (Bob,x,y,0,SOUTH);
      }

 Bob->mz_Cell=Cell;
}

/* implementation of library functions */

struct BTDInfo *QueryMyBlanker(void)

{
 return &MazeInfo;
}

Maze *InitMyBlanker(struct TagItem *TagList)

{
 struct BTDDrawInfo *BTDDrawInfo;
 ULONG *Error,Dummy;
 LONG CellSize,SolveDelay,Index;
 Maze *Bob;

 if ((BTDDrawInfo=(struct BTDDrawInfo *)
                   GetTagData(BTD_DrawInfo,NULL,TagList))==NULL) return NULL;
 Error=(ULONG *)GetTagData(BTD_Error,(ULONG)&Dummy,TagList);

 CellSize=GetTagData(MZ_CellSize,DEF_CELLSIZE,TagList);
 if ((BTDDrawInfo->BDI_Width<(CellSize*4+1))||
     (BTDDrawInfo->BDI_Height<(CellSize*4+1)))
  {
   *Error=BTDERR_Size;
   return NULL;
  }

 if ((Bob=AllocMaze(BTDDrawInfo,
                    (BTDDrawInfo->BDI_Width-1)/CellSize,
                    (BTDDrawInfo->BDI_Height-1)/CellSize))==NULL)
  {
   *Error=BTDERR_Memory;
   return NULL;
  }

 InitRandom (Bob,GetTagData(BTD_Instance,0L,TagList));

 SolveDelay=GetTagData(MZ_SolveDelay,DEF_SOLVEDELAY,TagList);
 if (SolveDelay==0L)
  {
   Bob->mz_SolDelay=0L;
   Bob->mz_SolPeriod=100L;
  }
 else
  if (SolveDelay<12L)
   {
    Bob->mz_SolDelay=1L;
    Bob->mz_SolPeriod=12L-SolveDelay;
   }
  else
   {
    Bob->mz_SolDelay=SolveDelay-10L;
    Bob->mz_SolPeriod=1L;
   }

 Bob->mz_NumCols=GetTagData(MZ_Colors,DEF_COLORS,TagList);
 if (Bob->mz_NumCols>NUM_RAINBOW_COLORS)
  {
   LONG ColNum,Col,RBCol;
   UBYTE *Red,*Green,*Blue,*Changed;

   Red=BTDDrawInfo->BDI_Red;
   Green=BTDDrawInfo->BDI_Green;
   Blue=BTDDrawInfo->BDI_Blue;
   Changed=BTDDrawInfo->BDI_Changed;
   ColNum=Bob->mz_NumCols/NUM_RAINBOW_COLORS+1L;
   Index=0L;
   for (RBCol=0L; RBCol<NUM_RAINBOW_COLORS; RBCol++)
    {
     if (RBCol==(Bob->mz_NumCols%NUM_RAINBOW_COLORS)) ColNum--;

     for (Col=0L; Col<ColNum; Col++)
      {
       Red[BTDDrawInfo->BDI_Pens[Index]]=RBRed[RBCol]+((RBRed[RBCol+1]-RBRed[RBCol])*Col)/ColNum;
       Green[BTDDrawInfo->BDI_Pens[Index]]=RBGreen[RBCol]+((RBGreen[RBCol+1]-RBGreen[RBCol])*Col)/ColNum;
       Blue[BTDDrawInfo->BDI_Pens[Index]]=RBBlue[RBCol]+((RBBlue[RBCol+1]-RBBlue[RBCol])*Col)/ColNum;
       Changed[BTDDrawInfo->BDI_Pens[Index++]]=TRUE;
      }
    }
  }
 else
  for (Index=0L; Index<Bob->mz_NumCols; Index++)
   {
    BTDDrawInfo->BDI_Red[BTDDrawInfo->BDI_Pens[Index]]=RBRed[Index];
    BTDDrawInfo->BDI_Green[BTDDrawInfo->BDI_Pens[Index]]=RBGreen[Index];
    BTDDrawInfo->BDI_Blue[BTDDrawInfo->BDI_Pens[Index]]=RBBlue[Index];
    BTDDrawInfo->BDI_Changed[BTDDrawInfo->BDI_Pens[Index]]=TRUE;
   }

 return Bob;
}

void AnimMyBlanker(Maze *Bob)

{
 if (Bob->mz_SolveMode)
  {
   SolveMaze (Bob,0,Bob->mz_StartY,Bob->mz_Width-1,Bob->mz_SolutionY);
   if (Bob->mz_Cell==NULL)
    {
     ULONG Index;

     Bob->mz_SolveMode=FALSE;

     for (Index=0L; Index<(Bob->mz_Width*Bob->mz_Height); Index++)
      Bob->mz_Cells[Index]=0;

     for (Index=0L; Index<((Bob->mz_Width+1)*Bob->mz_Height); Index++)
      Bob->mz_LeftWalls[Index]=0;
     
     for (Index=0L; Index<(Bob->mz_Width*(Bob->mz_Height+1)); Index++)
      Bob->mz_TopWalls[Index]=0;
    }
  }
 else
  {
   if (Bob->mz_Cell==NULL)
    {
     EraseRect (Bob->mz_RPort,
                Bob->mz_Left,Bob->mz_Top,
                Bob->mz_Left+Bob->mz_BTDDrawInfo->BDI_Width-1,
                Bob->mz_Top+Bob->mz_BTDDrawInfo->BDI_Height-1);

     SetAPen (Bob->mz_RPort,Bob->mz_BTDDrawInfo->BDI_Pens[Random(Bob,Bob->mz_NumCols)]);
     Move (Bob->mz_RPort,Bob->mz_Left,Bob->mz_Top);
     Draw (Bob->mz_RPort,Bob->mz_Left,Bob->mz_Top+Bob->mz_Height*Bob->mz_HeiStep );
     Draw (Bob->mz_RPort,Bob->mz_Left+Bob->mz_Width*Bob->mz_WidStep,
           Bob->mz_Top+Bob->mz_Height*Bob->mz_HeiStep);
     Draw (Bob->mz_RPort,Bob->mz_Left+Bob->mz_Width*Bob->mz_WidStep,Bob->mz_Top);
     Draw (Bob->mz_RPort,Bob->mz_Left,Bob->mz_Top);

     Bob->mz_StackLength=0L;
     Bob->mz_SolutionLength=0L;

     Bob->mz_StartY=Random(Bob,Bob->mz_Height);
     Bob->mz_SolutionY=Random(Bob,Bob->mz_Height);
    }

   ConstructMaze(Bob,0,Bob->mz_StartY,Bob->mz_Width-1,Bob->mz_SolutionY);
   if (Bob->mz_Cell==NULL)
    {
     Bob->mz_SolveMode=TRUE;

     Bob->mz_FirstCol=Random(Bob,Bob->mz_NumCols);
     DrawSolution (Bob,0,Bob->mz_StartY,Bob->mz_FirstCol+1L,WEST);
     DrawSolution (Bob,Bob->mz_Width-1,Bob->mz_SolutionY,Bob->mz_FirstCol+1L,EAST);
    }
  }
}

void EndMyBlanker(Maze *Bob)

{
 Stack *Cell;

 while (Cell=Pop(Bob)) FreeVec (Cell);
 FreeMaze (Bob);
}

ULONG PenCountMyBlanker(struct TagItem *TagList)

{
 return GetTagData(MZ_Colors,DEF_COLORS,TagList);
}
