home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff255.lzh / SunMaze / sunmaze.c < prev   
C/C++ Source or Header  |  1989-10-19  |  23KB  |  802 lines

  1. /*
  2.  *  DWR:  This file has been changed to implement shadow in the
  3.  *  3d presentation of the maze.
  4.  *  This is the original file from Fish 171:  Maze/3DDemo.c
  5.  *  All modifications are marked with "DWR:".
  6.  */
  7.  
  8. #include <proto/all.h>
  9.  
  10. #include <libraries/dosextens.h>
  11. #include <intuition/intuition.h>
  12. #include <exec/memory.h>
  13. #include <graphics/gfxmacros.h>
  14.  
  15. #define BITMAP
  16.  
  17. #include "maze.h"         /* This is our maze generator */
  18.  
  19. #define MENUITEMS 6
  20.  
  21. struct IntuiText item[MENUITEMS*2]=
  22. { 6,0,JAM2,0,0,NULL,NULL,NULL };
  23.  
  24. struct IntuiText abouttxt5=   /* Yes, this game needs lots of credits */
  25. { 7,0,JAM2,32,60,NULL,"keys to move",NULL};  /* DWR: changed */
  26. struct IntuiText abouttxt4=
  27. { 7,0,JAM2,12,50,NULL,"Use keypad cursor",&abouttxt5};  /* DWR: changed */
  28. struct IntuiText abouttxt3=
  29. { 4,0,JAM2,0,40,NULL,"Freely distributable",&abouttxt4};  /* DWR: changed */
  30.  
  31. struct IntuiText abouttxt3b=
  32. { 2,0,JAM2,36,30,NULL,"Dirk Reisig",&abouttxt3};  /* DWR: inserted */
  33. struct IntuiText abouttxt3a=
  34. { 1,0,JAM2,40,20,NULL,"Shadows by",&abouttxt3b};  /* DWR: inserted */
  35.  
  36. struct IntuiText abouttxt2=
  37. { 6,0,JAM2,24,10,NULL,"Werner Gunther",&abouttxt3a};  /* DWR: changed */
  38. struct IntuiText abouttxt1=
  39. { 6,0,JAM2,40,0,NULL,"Written by",&abouttxt2};
  40.  
  41.  
  42. struct MenuItem mi[MENUITEMS] =          /* main menu structures */
  43. {
  44.  NULL,0,0,70,11,
  45.  ITEMTEXT|ITEMENABLED|HIGHCOMP,
  46.  NULL,NULL,NULL,NULL,NULL,NULL
  47. };
  48. struct MenuItem sizemenu[MENUITEMS] =    /* sub menu for sizes */
  49. {
  50.  NULL,60,0,90,11,
  51.  ITEMTEXT|ITEMENABLED|HIGHCOMP|CHECKIT,
  52.  NULL,NULL,NULL,NULL,NULL,NULL
  53. };
  54. struct MenuItem about =                  /* about, credits & help */
  55. {
  56.  NULL,60,0,160,70,
  57.  ITEMTEXT|ITEMENABLED,
  58.  NULL,(APTR)&abouttxt1,NULL,NULL,NULL,NULL
  59. };
  60.  
  61. struct Menu menu=
  62. {
  63.  NULL,0,0,70,11,
  64.  MENUENABLED,
  65.  "Options",
  66.  mi
  67. };
  68.  
  69. struct NewScreen ns=                     /* screen low-rez, 8 colors */
  70. {
  71.  0,0,320,200,3,
  72.  1,0,
  73.  NULL,
  74.  CUSTOMSCREEN,
  75.  NULL,NULL,NULL,NULL
  76. };
  77.  
  78. struct NewWindow nw=                     /* window for menus & gadgets */
  79. {
  80.  0,1,286,199,
  81.  1,0,
  82.  CLOSEWINDOW|GADGETUP|MENUPICK|MENUVERIFY|VANILLAKEY,
  83.  BORDERLESS|NOCAREREFRESH|WINDOWCLOSE|ACTIVATE,
  84.  NULL, NULL,
  85.  "Maze 3D Demo",
  86.  NULL, NULL, NULL,NULL,NULL,NULL,
  87.  CUSTOMSCREEN
  88. };
  89.  
  90. struct Image mazeimage={0,0,0,0,1,0,4,4,0}; /* Image to display the maze */
  91.  
  92. char mtxt[MENUITEMS][9]=                    /* menu text */
  93. {
  94.  "Map","New Maze","Size","Demo","Quit","About"
  95. };
  96. char sizetxt[MENUITEMS][11]=                /* text for size menu */
  97. {
  98.  "Trivial","Simple","Normal","Advanced","Difficult","Impossible"
  99. };
  100.  
  101. struct GfxBase *GfxBase = NULL;
  102. struct IntuitionBase *IntuitionBase = NULL;
  103. struct Screen *screen = NULL;
  104. struct Window *window = NULL;
  105. struct BitMap *bm;
  106. struct IntuiMessage *msg;
  107. struct AreaInfo  areainfo;
  108. struct TmpRas tmpras;
  109. struct RastPort *rp;
  110.  
  111. ULONG  class,code;
  112. BOOL   WorkBench=FALSE,demomode=FALSE,forward();
  113. void   right(),left(),demo(),newmaze(),leave(),main(),show3d(),showmaze();
  114. void   statusline();
  115. short  i,j,xsize,ysize,mazesize=2,x,y,wayout,moves;
  116. char   *mymaze=NULL,areapts[7*5],*raster=NULL,buffer[20];
  117. short  dirincs[4][2]={{0,-1},{1,0},{0,1},{-1,0}};
  118. char   heading[][7]={"North"," East ","South"," West "};
  119.  
  120. void main(argc,argv)
  121. short argc;
  122. char argv[];
  123. {
  124.  if (!argc) WorkBench=TRUE;      /* open stuff */
  125.  if (!(IntuitionBase = (struct IntuitonBase*)
  126.   OpenLibrary("intuition.library",0L)))
  127.     leave("No Intuition Library");
  128.  if (!(GfxBase = (struct GfxBase*) OpenLibrary("graphics.library",0L)))
  129.     leave("No Graphics Library");
  130.  
  131.  for(i=0;i<MENUITEMS;i++)        /* set menu-strip */
  132.  {                               /* could have be done on declaration */
  133.   sizemenu[i]=sizemenu[0];
  134.   sizemenu[i].NextItem=&sizemenu[i+1];
  135.   sizemenu[i].ItemFill=(APTR)&item[i+MENUITEMS];
  136.   sizemenu[i].TopEdge=i*11;
  137.   item[i]=item[0];
  138.   item[i+MENUITEMS]=item[0];
  139.   item[i+MENUITEMS].IText=sizetxt[i];
  140.   item[i+MENUITEMS].LeftEdge=11;
  141.   item[i].IText=mtxt[i];
  142.   mi[i]=mi[0];
  143.   mi[i].NextItem=&mi[i+1];
  144.   mi[i].ItemFill=(APTR)&item[i];
  145.   mi[i].TopEdge=i*11;
  146.  }
  147.  mi[MENUITEMS-1].NextItem=NULL;
  148.  sizemenu[MENUITEMS-1].NextItem=NULL;
  149.  mi[2].SubItem=&sizemenu[0];
  150.  mi[5].SubItem=&about;
  151.  sizemenu[mazesize].Flags|=CHECKED;
  152.  
  153.  if (!(screen = (struct Screen*) OpenScreen(&ns))) /* open screen & window */
  154.     leave ("Can't open Screen");
  155.  bm = screen->ViewPort.RasInfo->BitMap;
  156.  rp = &screen->RastPort;
  157.  
  158.  nw.Screen=screen;
  159.  if (!(window = (struct Window*) OpenWindow(&nw))) leave("Can't open Window");
  160.  SetMenuStrip(window,&menu);
  161.  
  162. /*
  163. *  DWR: Following eight statements replace the original color setting.
  164. */
  165.  
  166.  SetRGB4(&screen->ViewPort,0, 0, 0, 0); /* Background, black */
  167.  SetRGB4(&screen->ViewPort,1, 1, 5, 2); /* Floor, in shadow, dark green */
  168.  SetRGB4(&screen->ViewPort,2, 2, 7, 1); /* Floor, in sun, light green */
  169.  SetRGB4(&screen->ViewPort,3, 8, 8, 8); /* Side wall, in shadow, dark grey */
  170.  SetRGB4(&screen->ViewPort,4,12,12,12); /* Side wall, in sun, light grey */
  171.  SetRGB4(&screen->ViewPort,5,10,10,10); /* Front wall, in shadow, dark white */
  172.  SetRGB4(&screen->ViewPort,6,14,14,14); /* Front wall, in sun, light white */
  173.  SetRGB4(&screen->ViewPort,7, 8, 8,15); /* Sky, blue  */
  174.  
  175.  /* stuff needed by FloodFill, AreaFill */
  176.  if(!(raster=(char *)AllocRaster(192,188))) leave("Can't allocate TmpRaster");
  177.  InitTmpRas(&tmpras,raster,4512);
  178.  rp->TmpRas=&tmpras;
  179.  InitArea(&areainfo,areapts,7);
  180.  rp->AreaInfo=&areainfo;
  181.  BNDRYOFF(rp);
  182.  
  183.  for(i=0;i<3;i++) /* Draw status-display box */
  184.  {
  185.   SetAPen(rp,i+3);
  186.   AreaMove(rp,190+5*i,12+5*i);
  187.   AreaDraw(rp,319-5*i,12+5*i);
  188.   AreaDraw(rp,319-5*i,125-5*i);
  189.   AreaDraw(rp,319-5*i-5,125-5*i-5);
  190.   AreaDraw(rp,319-5*i-5,12+i*5+5);
  191.   AreaDraw(rp,190+5*i+5,12+i*5+5);
  192.   AreaEnd(rp);
  193.   SetAPen(rp,i+2);
  194.   AreaMove(rp,190+5*i,12+5*i);
  195.   AreaDraw(rp,190+5*i,125-5*i);
  196.   AreaDraw(rp,319-5*i,125-5*i);
  197.   AreaDraw(rp,319-5*i-5,125-5*i-5);
  198.   AreaDraw(rp,319-5*i-5,12+i*5+5);
  199.   AreaDraw(rp,190+5*i+5,12+i*5+5);
  200.   AreaEnd(rp);
  201.  }
  202.  
  203.  newmaze();
  204.  
  205.  for(;;)           /* main loop, wait for a message if not in demo-mode */
  206.  {
  207.   if (!demomode) WaitPort(window->UserPort);
  208.   else demo();
  209.   if(msg=(struct IntuiMessage*)GetMsg(window->UserPort))
  210.   {
  211.    demomode=FALSE;
  212.    class=msg->Class;
  213.    code=msg->Code;
  214.    ReplyMsg(msg);
  215.    switch(class)
  216.    {
  217.     case CLOSEWINDOW:
  218.      leave("");
  219.     case VANILLAKEY:
  220.      if(y!=wayout || x!=xsize-3)
  221.       switch(code) /* we check numbers 6/4/8, these are arrows on the */
  222.       {            /* num pad keys, so we don't need RawKeyConvert */
  223.        case '8':
  224.         forward();
  225.         break;
  226.        case '4':
  227.         left();
  228.         break;
  229.        case '6':
  230.         right();
  231.         break;
  232.       }
  233.      break;
  234.     case MENUPICK:
  235.       switch(ITEMNUM(code))
  236.       {
  237.        case 0:         /* map */
  238.         showmaze();
  239.         moves+=30;
  240.         break;         /* New Maze */
  241.        case 1:
  242.         newmaze();
  243.         break;
  244.        case 2:
  245.         if(SUBNUM(code)==mazesize) break;
  246.         sizemenu[mazesize].Flags&=~CHECKED;
  247.         mazesize=SUBNUM(code);
  248.         sizemenu[mazesize].Flags|=CHECKED;
  249.         newmaze();
  250.         break;
  251.        case 3:         /* Demo  */
  252.         demomode=TRUE;
  253.         break;
  254.        case 4:         /* Quit  */
  255.         leave("");
  256.        case 5:         /* About */
  257.            ; /* Inserted ; to make Aztec happy -- PDS(1) -- 31-jul-88 */
  258.       }
  259.    }
  260.   }
  261.  }
  262. }
  263.  
  264. void leave(error)
  265. char *error;
  266. {
  267.  BPTR file;
  268.                    /* Free Resouces & Exit */
  269.  if(window)        CloseWindow(window);
  270.  if(screen)        CloseScreen(screen);
  271.  if(IntuitionBase) CloseLibrary(IntuitionBase);
  272.  if(GfxBase)       CloseLibrary(GfxBase);
  273.  if (mymaze)       FreeMem(mymaze,(xsize>>3)*ysize);
  274.  if (raster)       FreeRaster(raster,192,188);
  275.  
  276.  if (*error && WorkBench &&
  277.      (file=Open("con:20/70/400/60/Maze 3D Demo",MODE_OLDFILE)))
  278.  {
  279.   Write(file,error,strlen(error));
  280.   Delay(200L);
  281.   Close(file);
  282.  }
  283.  else if (*error) printf("%s\n",error);
  284.  exit(0);
  285. }
  286.  
  287. void newmaze()
  288. {
  289.  if (mymaze) FreeMem(mymaze,(xsize>>3)*ysize); /* Free old maze */
  290.  xsize=32+mazesize*16;                         /* get new dimension */
  291.  ysize=12+mazesize*12;
  292.  if (!(mymaze=(char*) AllocMem((xsize>>3)*ysize,MEMF_CHIP|MEMF_CLEAR)))
  293.      leave("Out of chip memory");              /* allocate new one */
  294.  SetAPen(rp,6);                                /* clear status display */
  295.  RectFill(rp,205,27,304,110);
  296.  SetAPen(rp,1);
  297.  statusline(10,"Moves:");
  298.  statusline(30,"Looking");
  299.  statusline(60,"Size:");
  300.  sprintf(buffer,"%ld*%ld",xsize,ysize);
  301.  statusline(70,buffer);
  302.  
  303.  maze(xsize,ysize,mymaze);                     /* genarate a new maze */
  304.  seed = FastRand(seed);
  305.  y= ((seed & 0x7ffe) % (ysize-4)+2) & 0x7ffe;  /* random start point */
  306.  x= 2;
  307.  seed = FastRand(seed);
  308.  wayout = ((seed & 0x7ffe) % (ysize-4)+2) & 0x7ffe;  /* random exit */
  309.  MAZESET(xsize-3,wayout,xsize,mymaze);               /* open exit */
  310.  direction=1;                                    /* heading right (east) */
  311.  statusline(40,heading[direction]);
  312.  moves=0;
  313.  show3d();
  314.  showmaze();
  315. }
  316.  
  317. void statusline(y,text)
  318. short y;
  319. char *text;
  320. {                                  /* Write text, centered, into */
  321.  Move(rp,255-strlen(text)*4,27+y); /* status-display */
  322.  SetAPen(rp,1);
  323.  SetBPen(rp,6);
  324.  Text(rp,text,strlen(text));
  325. }
  326.  
  327. void showmaze()                   /* show the maze */
  328. {
  329.  mazeimage.Width=xsize;           /* we define a Image-structure on our */
  330.  mazeimage.Height=ysize;          /* bitmapped maze */
  331.  mazeimage.ImageData=(short*)mymaze;
  332.  DrawImage(rp,&mazeimage,255-(xsize/2),127);
  333.                                                /* wait for a message */
  334.  while(! window->UserPort->mp_MsgList.lh_Head->ln_Succ)
  335.  {
  336.   SetAPen(rp,++i&7);                        /* exit and current position */
  337.   WritePixel(rp,255-(xsize/2)+x,127+y);     /* are blinking */
  338.   WritePixel(rp,253-(xsize/2)+xsize,127+wayout);
  339.   Delay(6L);
  340.  }
  341.  SetAPen(rp,0);
  342.  RectFill(rp,191,127,319,199);
  343. }
  344.  
  345.  
  346. /*
  347. *  DWR: The original 3d function is replaced by the one
  348. *  at the end of this file..
  349. */
  350.  
  351.  
  352. void demo()    /* demo mode: follow the left-hand wall until we get to */
  353. {              /* the exit */
  354.  long delay;
  355.                /* be fast if the exit is far away, slow if it gets nearer */
  356.  delay=19-18*(xsize-3-x+((wayout-y)<0?-(wayout-y):(wayout-y)))/
  357.           ((wayout<ysize/2? ysize-wayout:wayout)+xsize-3);
  358.  
  359.  if(y==wayout && x==xsize-3) /* did we reach the exit ?*/
  360.  {
  361.   demomode=FALSE;            /* stop if we did */
  362.   return;
  363.  }                           /* is it possible to turn left ? */
  364.  if(MAZETEST(x+dirincs[(direction-1)&3][0],y+dirincs[(direction-1)&3][1],
  365.              xsize,mymaze))
  366.  {
  367.   left();                    /* yes, turn left */
  368.   Delay(delay);
  369.   forward();                 /* and one step forward */
  370.  }
  371.  else if(!forward()) right(); /* if not try to move forward, if everything */
  372.                               /* fails, turn right */
  373.  Delay(delay);
  374. }
  375.  
  376. BOOL forward()                /* move one step forward if possible */
  377. {
  378.  if(!(MAZETEST(x+dirincs[direction][0],
  379.              y+dirincs[direction][1],xsize,mymaze))) return(FALSE);
  380.  
  381.  x+=dirincs[direction][0];
  382.  y+=dirincs[direction][1];
  383.  moves++;
  384.  sprintf(buffer," %ld/%ld ",
  385.          moves,xsize-3-x+((wayout-y)<0?-(wayout-y):(wayout-y)));
  386.  statusline(20,buffer);
  387.  show3d();
  388.  
  389.  if(y==wayout && x==xsize-3)  /* has the exit been reached ?*/
  390.  {
  391.   SetAPen(rp,1);              /* yes, write some stupid text */
  392.   SetBPen(rp,7);
  393.   Move(rp,58,102);  /*  DWR: changed  */
  394.   Text(rp,"Solved in",9);
  395.   SetAPen(rp,6);
  396.   SetBPen(rp,2);  /*  DWR: changed  */
  397.   sprintf(buffer,"%ld moves.",moves);
  398.   Move(rp,94-strlen(buffer)*4,116);
  399.   Text(rp,buffer,strlen(buffer));
  400.  }
  401.  return(TRUE);
  402. }
  403.  
  404. void left()                 /* turn left */
  405. {
  406.  direction=(--direction) & 3;
  407.  show3d();
  408.  statusline(40,heading[direction]);
  409. }
  410.  
  411. void right()                /* turn right */
  412. {
  413.  direction=(++direction) & 3;
  414.  show3d();
  415.  statusline(40,heading[direction]);
  416. }
  417.  
  418.  
  419. /*
  420.  *  DWR: The new 3d fucntion and its support.
  421.  *  The basic form of the display is a number of (not drawn) paralel
  422.  *  squares.
  423.  *  Starting at the middle of the display (roughly 200*200) the
  424.  *  smallest square has a side of one dot. The next square two dots.
  425.  *  This increments via 4, 8, 16, 32, 64 to 128 dots.  This way
  426.  *  we can see 8 squares deep.
  427.  *  By drawing diagonals we separate walls from the floor and the
  428.  *  sky.  When there is a cross-passage, we donot draw these
  429.  *  diagonals but extent the square in the direction of the cross
  430.  *  path until we reach the nearer square.
  431.  *  The shadows are based on a sun at 60 degrees above the horizon
  432.  *  and in the south-west (3 o'clock).  This way we have shadow-patterns
  433.  *  which can be expressed in the number system of the squares. (You
  434.  *  remember the 30-60-90 triangle?)
  435.  *  The order of drawing is chosen to mask away some bad drawn shadows
  436.  *  and irregularities in conjunction with edges.
  437.  */
  438.  
  439.  
  440. #define MAXDEPTH 8    /* 8 squares deep                */
  441.  
  442. #define SHADOW 1    /* The value you must subtract from a        */
  443.             /* wall or floor to get it shaded        */
  444. #define SKY   7
  445. #define FLOOR 2        /* 2 -> light green, 1 -> dark green        */
  446. #define SIDE  4        /* 4 -> light grey,  3-> dark grey        */
  447. #define FRONT 6        /* 6 -> light white, 5-> dark white (grey of course) */
  448.  
  449. #define HMID 94        /* The horizontal middle of the display        */
  450. #define VMID 105    /* The vertical middle                */
  451.             /* This was 106, which was wrong        */
  452.  
  453. #define LEFT -1        /* Factors which define the direction        */
  454. #define RIGHT 1        /* from the horizontal middle            */
  455.  
  456.  
  457. short Shadow[]={ 0,0,SHADOW,SHADOW }; /* Change this to reposition the sun */
  458.  
  459.  
  460. void show3d()
  461. {
  462.  
  463.   short Side;        /* Can be "LEFT" or "RIGHT"            */
  464.   short Wall;        /* Actual distance we can see            */
  465.   short Depth;        /* Level we are drawing in            */
  466.   short Inner;        /* Size of the wall in the square we are    */
  467.   short Outer;        /* Size of the wall one level nearer        */
  468.   short Middle;        /* Size of the wall between those two        */
  469.   short InMid;        /* Size of shadow far from us            */
  470.   short OutMid;        /* Size of shadow near to us            */
  471.   short Minim;        /* The minimal size we use with drawing shadows    */
  472.   short MazeExit;    /* Flag set if we are looking at the exit    */
  473.  
  474. /*
  475.   WaitBOVP(rp);
  476. */
  477.  
  478.  /*
  479.   *  First we draw the pampas.  It consists of floor and
  480.   *  the sky, separated by the horizon.
  481.   *  All floor under the horizon is light green (in the sun),
  482.   *  and all above is blue sky.
  483.   */
  484.  
  485.   SetAPen(rp,SKY);
  486.   RectFill(rp,0,VMID-HMID,2*HMID,VMID);
  487.   SetAPen(rp,FLOOR);
  488.   RectFill(rp,0,VMID+1,2*HMID,VMID+HMID);
  489.  
  490.  
  491.  /*
  492.   *  Find out how far we can see in the maze.
  493.   *  That is howmuch squares is the opposite wall
  494.   *  from us away.  If further than we can draw, this
  495.   *  value represents the deepest square we can draw (8).
  496.   */
  497.   
  498.   for (Depth=1; Depth<MAXDEPTH; Depth++){
  499.     if (!(MAZETEST(x+Depth*dirincs[direction][0],
  500.                    y+Depth*dirincs[direction][1],
  501.                    xsize,mymaze)))
  502.     break;
  503.   }
  504.   
  505.  /*
  506.   *  Keep this value for later when we draw the opposite wall.
  507.   *  Determine the smallest value we use with drawing shades.
  508.   *  And perhaps we are looking at the exit.
  509.   */
  510.  
  511.   Wall=Depth-1;
  512.   Minim=1<<((MAXDEPTH-1)-Depth);
  513.   MazeExit= ((y==wayout)&&((x+Wall*dirincs[direction][0])==xsize-2));
  514.     
  515.  /*
  516.   *  Draw first the left side of the view, followed
  517.   *  by the right side.
  518.   */
  519.   
  520.   for (Side=LEFT; Side<=RIGHT; Side+=2){
  521.  
  522.    /*
  523.     *  Loop for drawing in all squares, beginning at
  524.     *  the farrest level, ending at our present position.
  525.     */
  526.     
  527.     for (Depth=Wall; Depth>=0; Depth--){ 
  528.  
  529.      /*
  530.       *  Detemine some values we use in this square.
  531.       */
  532.       
  533.       Inner=1<<((MAXDEPTH-2)-Depth);  /* Half size of this square          */
  534.       Outer=Inner<<1;                 /* Half size on one square nearer    */
  535.       Middle=(Outer+Inner)/2;         /* The same size of a square between */
  536.       if (Outer>HMID) Outer=HMID;     /* If too near (larger than display  */
  537.       if (Middle>HMID) Middle=HMID;   /* clip it to a useful size          */
  538.  
  539.      /*
  540.       *  Are we dealing with a wall or a cross-passage?
  541.       */
  542.       
  543.       if (!IsPassage(Side,Depth)){
  544.  
  545.        /*
  546.         *  We draw a wall and its shadow if visable.
  547.         *  The shadow is visable if the surface of the
  548.         *  wall is in the shadow.
  549.         */
  550.  
  551.         if (Shadow[(direction+Side)&3]){
  552.  
  553.          /*  The shadow is on our path, now is
  554.           *  it directed toward us or from us away?
  555.           */
  556.           
  557.           if (Shadow[direction]){          /*  To us    */
  558.             InMid=Middle;
  559.             OutMid=Middle<<1;
  560.             if (OutMid>HMID) OutMid=HMID;
  561.           } else{                          /*  From us  */
  562.             InMid=Middle/2+1;
  563.             if (InMid<Minim) InMid=Minim;
  564.             OutMid=Middle;
  565.           }
  566.  
  567.          /*
  568.           *  Draw this shadow of the side wall on out path
  569.           */
  570.           
  571.           SetAPen(rp,FLOOR-SHADOW);
  572.           AreaMove(rp,HMID,VMID+InMid);
  573.           AreaDraw(rp,HMID,VMID+OutMid);
  574.           AreaDraw(rp,HMID+Side*Outer,VMID+Outer); 
  575.           AreaDraw(rp,HMID+Side*Inner,VMID+Inner); 
  576.           AreaEnd(rp);
  577.         }
  578.         /*  End of drawing shadow on our path  */
  579.  
  580.        /*
  581.         *  Draw the side wall itself using the color of
  582.         *  a side wall, but modify it by a possible
  583.         *  shade correction.
  584.         */
  585.         
  586.         SetAPen(rp,SIDE-Shadow[(direction+Side)&3]);
  587.         AreaMove(rp,HMID+Side*Inner,VMID-Inner); 
  588.         AreaDraw(rp,HMID+Side*Inner,VMID+Inner); 
  589.         AreaDraw(rp,HMID+Side*Outer,VMID+Outer); 
  590.         AreaDraw(rp,HMID+Side*Outer,VMID-Outer); 
  591.         AreaEnd(rp);
  592.  
  593.        /*
  594.         *  If we are the first time in this loop,
  595.         *  and the opposite wall is in the shadow,
  596.         *  and the just drawn side wall is in the sun,
  597.         *  draw the shadow from the opposite wall on it.
  598.         */
  599.         
  600.         if ((Depth==Wall)&& Shadow[direction]&& !Shadow[(direction+Side)&3]){
  601.           SetAPen(rp,SIDE-SHADOW);
  602.           AreaMove(rp,HMID+Side*Inner,VMID-Inner);
  603.           AreaDraw(rp,HMID+Side*Inner,VMID+Inner);
  604.           AreaDraw(rp,HMID+Side*Middle,VMID+Middle);
  605.           AreaEnd(rp);
  606.         }
  607.       }
  608.       /*  End of dealing with a side wall */
  609.       
  610.       else{
  611.       
  612.        /*
  613.         *  Here we are dealing with a cross passage,
  614.         *  We first draw some shadows on the floor,
  615.         *  as well on our path, as on the cross passage.
  616.         */
  617.         
  618.         SetAPen(rp,FLOOR-SHADOW);
  619.  
  620.        /*
  621.         *  Is the shadow in the direction of our path?
  622.         */
  623.          
  624.         if (Shadow[(direction+Side)&3]){
  625.           
  626.          /*
  627.           *  The shadow is in the direction of our path,
  628.           *  now is it directed from us away?
  629.           */
  630.           
  631.           if (Shadow[direction]){
  632.             
  633.            /*
  634.             *  The crosswall is in the shade.
  635.             *  Draw the shadow on the coss path.
  636.             *  The distiction between the sides is to meet
  637.             *  the RectFill() form.
  638.             */
  639.             
  640.             if (Side==LEFT) 
  641.               RectFill(rp,HMID-Outer,VMID+Inner,HMID,VMID+Middle);
  642.             else
  643.               RectFill(rp,HMID,VMID+Inner,HMID+Outer,VMID+Middle);
  644.           }
  645.           else{
  646.           
  647.            /*
  648.             *  The cross wall is in the sun.
  649.             *  Draw the shadow of the other side.
  650.             */
  651.             
  652.             if (Side==LEFT) 
  653.               RectFill(rp,HMID-Outer,VMID+Middle,HMID,VMID+Outer);
  654.             else
  655.               RectFill(rp,HMID,VMID+Middle,HMID+Outer,VMID+Outer);
  656.           }
  657.         }
  658.         /*  End of shadow directed to our path  */
  659.  
  660.         else{
  661.           
  662.          /*
  663.           *  The shadow is directed from our path away.
  664.           *  Now draw the shadow on the cross path if
  665.           *  the cross wall is in the shade.
  666.           */
  667.           
  668.           if (Shadow[direction]){
  669.             AreaMove(rp,HMID+Side*Inner,VMID+Inner);
  670.             AreaDraw(rp,HMID+Side*Outer,VMID+Inner);
  671.             AreaDraw(rp,HMID+Side*Outer,VMID+(Inner+Outer)/2);
  672.             AreaEnd(rp);
  673.           }
  674.         }
  675.  
  676.        /*
  677.         *  If we are here for the first time, 
  678.         *  and the opposite wall is visable,
  679.         *  and it is in the shade,
  680.         *  extent the shadow of the opposite wall to
  681.         *  the one from the cross wall. (A tiny triangle)
  682.         */
  683.  
  684.         if ((Depth==Wall)&&(Depth<MAXDEPTH)&&(Shadow[direction])){
  685.           AreaMove(rp,HMID+Side*Inner,VMID+Inner);
  686.           AreaDraw(rp,HMID+Side*Middle,VMID+Middle);
  687.           AreaDraw(rp,HMID+Side*Outer,VMID+Middle);
  688.           AreaDraw(rp,HMID+Side*Outer,VMID+Inner);
  689.           AreaEnd(rp);
  690.         }
  691.  
  692.        /*
  693.         *  If we are not dealing with the exit's cross path
  694.         *  draw the cross wall itself.
  695.         */
  696.         
  697.         if (!(MazeExit&&(Depth>(Wall-1)))){
  698.            SetAPen(rp,FRONT-Shadow[direction]);
  699.           if (Side==RIGHT)
  700.             RectFill(rp,HMID+Inner,VMID-Inner,HMID+Outer,VMID+Inner);
  701.           else 
  702.             RectFill(rp,HMID-Outer,VMID-Inner,HMID-Inner,VMID+Inner);
  703.         }
  704.  
  705.       }
  706.       /*  End of drawing a cross passage (or side wall)  */
  707.     }
  708.     /*  End of drawing in subsequent squares  */
  709.   }
  710.   /*  End of drawing the left and right side ot the picture  */
  711.   
  712.  /*
  713.   *  Now we have to draw the opposite wall
  714.   *  or the exit if not too far away
  715.   */
  716.  
  717.   Depth=Wall;
  718.  
  719.   if (Depth<MAXDEPTH-1){
  720.     
  721.    /*
  722.     *  It is not too far away.
  723.     *  Fill in again those sizes.
  724.     */
  725.     
  726.     Inner=1<<((MAXDEPTH-2)-Depth);
  727.     Outer=Inner<<1;
  728.     Middle=(Outer+Inner)/2;
  729.     if (Outer>HMID) Outer=HMID;
  730.     if (Middle>HMID) Middle=HMID;
  731.  
  732.    /*
  733.     *  Are we not looking at the exit?
  734.     */
  735.     
  736.     if (!MazeExit){
  737.       
  738.      /*
  739.       *  We are looking at an opposite wall.
  740.       *  Draw its shadow on the floor if it is in the shade.
  741.       */
  742.       
  743.       if (Shadow[direction]){
  744.         SetAPen(rp,FLOOR-SHADOW);
  745.         AreaMove(rp,HMID+1-Inner,VMID+Inner);
  746.         AreaDraw(rp,HMID+1-Middle,VMID+Middle);
  747.         AreaDraw(rp,HMID-1+Middle,VMID+Middle);
  748.         AreaDraw(rp,HMID-1+Inner,VMID+Inner);
  749.         AreaEnd(rp);
  750.       }
  751.       
  752.      /*
  753.       *  Draw the opposite wall itself.
  754.       */
  755.       
  756.       SetAPen(rp,FRONT-Shadow[direction]);
  757.       RectFill(rp,HMID-Inner,VMID-Inner,HMID+Inner,VMID+Inner);
  758.  
  759.      /*
  760.       *  If the opposite wall is bounded to a side wall,
  761.       *  and this side wall is in the shadow,
  762.       *  and the opposite wall is in the sun,
  763.       *  draw the shadow of the side wall on the opposite wall.
  764.       */
  765.       
  766.       for (Side=LEFT; Side<=RIGHT; Side+=2){
  767.         if (
  768.             (!IsPassage(Side,Depth))&&
  769.             (Shadow[(direction+Side)&3])&&
  770.             (!Shadow[direction])
  771.            ){
  772.           SetAPen(rp,FRONT-SHADOW);
  773.           AreaMove(rp,HMID+Side*Inner,VMID-Inner);
  774.           AreaDraw(rp,HMID+Side*Inner,VMID+Inner);
  775.           AreaDraw(rp,HMID,VMID+Inner);
  776.           AreaEnd(rp);
  777.         }
  778.       }
  779.     }
  780.   }
  781. }
  782.  
  783.  
  784.  
  785. /*
  786.  *  This was original in line, but it disturbed the view over the
  787.  *  code.  Placing it in a function made the clearity of the show3d()
  788.  *  function better.
  789.  *  This function returns the presence of a cross passage at <Side>'s
  790.  *  side and <Depth> from us away.
  791.  */
  792.  
  793. IsPassage(Side,Depth)
  794. short Side,Depth;
  795. {
  796.   register int xx,yy;
  797.   xx=x+dirincs[(direction+Side)&3][0]+Depth*dirincs[direction][0];
  798.   yy=y+dirincs[(direction+Side)&3][1]+Depth*dirincs[direction][1];
  799.   return(MAZETEST(xx,yy, xsize,mymaze));
  800. }
  801.  
  802.