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

  1. #include <libraries/dosextens.h>
  2. #include <intuition/intuition.h>
  3. #include <exec/memory.h>
  4. #include <graphics/gfxmacros.h>
  5.  
  6. #define BITMAP
  7.  
  8. #include "maze.h"         /* This is our maze generator */
  9.  
  10. #define MENUITEMS 6
  11.  
  12. struct IntuiText item[MENUITEMS*2]=
  13. { 6,0,JAM2,0,0,NULL,NULL,NULL };
  14.  
  15. struct IntuiText abouttxt5=   /* Yes, this game needs lots of credits */
  16. { 7,0,JAM2,32,40,NULL,"keys to move",NULL};
  17. struct IntuiText abouttxt4=
  18. { 7,0,JAM2,12,30,NULL,"Use keypad cursor",&abouttxt5};
  19. struct IntuiText abouttxt3=
  20. { 4,0,JAM2,0,20,NULL,"Freely distributable",&abouttxt4};
  21. struct IntuiText abouttxt2=
  22. { 6,0,JAM2,24,10,NULL,"Werner Gunther",&abouttxt3};
  23. struct IntuiText abouttxt1=
  24. { 6,0,JAM2,40,0,NULL,"Written by",&abouttxt2};
  25.  
  26. struct MenuItem mi[MENUITEMS] =          /* main menu structures */
  27. {
  28.  NULL,0,0,70,11,
  29.  ITEMTEXT|ITEMENABLED|HIGHCOMP,
  30.  NULL,NULL,NULL,NULL,NULL,NULL
  31. };
  32. struct MenuItem sizemenu[MENUITEMS] =    /* sub menu for sizes */
  33. {
  34.  NULL,60,0,90,11,
  35.  ITEMTEXT|ITEMENABLED|HIGHCOMP|CHECKIT,
  36.  NULL,NULL,NULL,NULL,NULL,NULL
  37. };
  38. struct MenuItem about =                  /* about, credits & help */
  39. {
  40.  NULL,60,0,160,50,
  41.  ITEMTEXT|ITEMENABLED,
  42.  NULL,(APTR)&abouttxt1,NULL,NULL,NULL,NULL
  43. };
  44.  
  45. struct Menu menu=
  46. {
  47.  NULL,0,0,70,11,
  48.  MENUENABLED,
  49.  "Options",
  50.  mi
  51. };
  52.  
  53. struct NewScreen ns=                     /* screen low-rez, 8 colors */
  54. {
  55.  0,0,320,200,3,
  56.  1,0,
  57.  NULL,
  58.  CUSTOMSCREEN,
  59.  NULL,NULL,NULL,NULL
  60. };
  61.  
  62. struct NewWindow nw=                     /* window for menus & gadgets */
  63. {
  64.  0,1,286,199,
  65.  1,0,
  66.  CLOSEWINDOW|GADGETUP|MENUPICK|MENUVERIFY|VANILLAKEY,
  67.  BORDERLESS|NOCAREREFRESH|WINDOWCLOSE|ACTIVATE,
  68.  NULL, NULL,
  69.  "Maze 3D Demo",
  70.  NULL, NULL, NULL,NULL,NULL,NULL,
  71.  CUSTOMSCREEN
  72. };
  73.  
  74. struct Image mazeimage={0,0,0,0,1,0,4,4,0}; /* Image to display the maze */
  75.  
  76. char mtxt[MENUITEMS][9]=                    /* menu text */
  77. {
  78.  "Map","New Maze","Size","Demo","Quit","About"
  79. };
  80. char sizetxt[MENUITEMS][11]=                /* text for size menu */
  81. {
  82.  "Trivial","Simple","Normal","Advanced","Difficult","Impossible"
  83. };
  84.  
  85. struct GfxBase *GfxBase = NULL;
  86. struct IntuitionBase *IntuitionBase = NULL;
  87. struct Screen *screen = NULL;
  88. struct Window *window = NULL;
  89. struct BitMap *bm;
  90. struct IntuiMessage *msg;
  91. struct AreaInfo  areainfo;
  92. struct TmpRas tmpras;
  93. struct RastPort *rp;
  94.  
  95. ULONG  class,code;
  96. BOOL   WorkBench=FALSE,demomode=FALSE,forward();
  97. void   right(),left(),demo(),newmaze(),leave(),main(),show3d(),showmaze();
  98. void   statusline();
  99. short  i,j,xsize,ysize,mazesize=2,x,y,wayout,moves;
  100. char   *mymaze=NULL,areapts[7*5],*raster=NULL,buffer[20];
  101. short  dirincs[4][2]={{0,-1},{1,0},{0,1},{-1,0}};
  102. char   heading[][7]={"North"," East ","South"," West "};
  103.  
  104. void main(argc,argv)
  105. short argc;
  106. char argv[];
  107. {
  108.  if (!argc) WorkBench=TRUE;      /* open stuff */
  109.  if (!(IntuitionBase = (struct IntuitonBase*)
  110.   OpenLibrary("intuition.library",0L)))
  111.     leave("No Intuition Library");
  112.  if (!(GfxBase = (struct GfxBase*) OpenLibrary("graphics.library",0L)))
  113.     leave("No Graphics Library");
  114.  
  115.  for(i=0;i<MENUITEMS;i++)        /* set menu-strip */
  116.  {                               /* could have be done on declaration */
  117.   sizemenu[i]=sizemenu[0];
  118.   sizemenu[i].NextItem=&sizemenu[i+1];
  119.   sizemenu[i].ItemFill=(APTR)&item[i+MENUITEMS];
  120.   sizemenu[i].TopEdge=i*11;
  121.   item[i]=item[0];
  122.   item[i+MENUITEMS]=item[0];
  123.   item[i+MENUITEMS].IText=sizetxt[i];
  124.   item[i+MENUITEMS].LeftEdge=11;
  125.   item[i].IText=mtxt[i];
  126.   mi[i]=mi[0];
  127.   mi[i].NextItem=&mi[i+1];
  128.   mi[i].ItemFill=(APTR)&item[i];
  129.   mi[i].TopEdge=i*11;
  130.  }
  131.  mi[MENUITEMS-1].NextItem=NULL;
  132.  sizemenu[MENUITEMS-1].NextItem=NULL;
  133.  mi[2].SubItem=&sizemenu[0];
  134.  mi[5].SubItem=&about;
  135.  sizemenu[mazesize].Flags|=CHECKED;
  136.  
  137.  if (!(screen = (struct Screen*) OpenScreen(&ns))) /* open screen & window */
  138.     leave ("Can't open Screen");
  139.  bm = screen->ViewPort.RasInfo->BitMap;
  140.  rp = &screen->RastPort;
  141.  
  142.  nw.Screen=screen;
  143.  if (!(window = (struct Window*) OpenWindow(&nw))) leave("Can't open Window");
  144.  SetMenuStrip(window,&menu);
  145.  
  146.  SetRGB4(&screen->ViewPort,0,0,0,0); /* set colors, 1-7 is a grey scale */
  147.  for(i=1;i<7;i++) SetRGB4(&screen->ViewPort,i,2+2*i,2+2*i,2+2*i);
  148.  SetRGB4(&screen->ViewPort,7,8,8,15);
  149.  
  150.  /* stuff needed by FloodFill, AreaFill */
  151.  if(!(raster=(char *)AllocRaster(192,188))) leave("Can't allocate TmpRaster");
  152.  InitTmpRas(&tmpras,raster,4512);
  153.  rp->TmpRas=&tmpras;
  154.  InitArea(&areainfo,areapts,7);
  155.  rp->AreaInfo=&areainfo;
  156.  BNDRYOFF(rp);
  157.  
  158.  for(i=0;i<3;i++) /* Draw status-display box */
  159.  {
  160.   SetAPen(rp,i+3);
  161.   AreaMove(rp,190+5*i,12+5*i);
  162.   AreaDraw(rp,319-5*i,12+5*i);
  163.   AreaDraw(rp,319-5*i,125-5*i);
  164.   AreaDraw(rp,319-5*i-5,125-5*i-5);
  165.   AreaDraw(rp,319-5*i-5,12+i*5+5);
  166.   AreaDraw(rp,190+5*i+5,12+i*5+5);
  167.   AreaEnd(rp);
  168.   SetAPen(rp,i+2);
  169.   AreaMove(rp,190+5*i,12+5*i);
  170.   AreaDraw(rp,190+5*i,125-5*i);
  171.   AreaDraw(rp,319-5*i,125-5*i);
  172.   AreaDraw(rp,319-5*i-5,125-5*i-5);
  173.   AreaDraw(rp,319-5*i-5,12+i*5+5);
  174.   AreaDraw(rp,190+5*i+5,12+i*5+5);
  175.   AreaEnd(rp);
  176.  }
  177.  
  178.  newmaze();
  179.  
  180.  for(;;)           /* main loop, wait for a message if not in demo-mode */
  181.  {
  182.   if (!demomode) WaitPort(window->UserPort);
  183.   else demo();
  184.   if(msg=(struct IntuiMessage*)GetMsg(window->UserPort))
  185.   {
  186.    demomode=FALSE;
  187.    class=msg->Class;
  188.    code=msg->Code;
  189.    ReplyMsg(msg);
  190.    switch(class)
  191.    {
  192.     case CLOSEWINDOW:
  193.      leave("");
  194.     case VANILLAKEY:
  195.      if(y!=wayout || x!=xsize-3)
  196.       switch(code) /* we check numbers 6/4/8, these are arrows on the */
  197.       {            /* num pad keys, so we don't need RawKeyConvert */
  198.        case '8':
  199.         forward();
  200.         break;
  201.        case '4':
  202.         left();
  203.         break;
  204.        case '6':
  205.         right();
  206.         break;
  207.       }
  208.      break;
  209.     case MENUPICK:
  210.       switch(ITEMNUM(code))
  211.       {
  212.        case 0:         /* map */
  213.         showmaze();
  214.         moves+=30;
  215.         break;         /* New Maze */
  216.        case 1:
  217.         newmaze();
  218.         break;
  219.        case 2:
  220.         if(SUBNUM(code)==mazesize) break;
  221.         sizemenu[mazesize].Flags&=~CHECKED;
  222.         mazesize=SUBNUM(code);
  223.         sizemenu[mazesize].Flags|=CHECKED;
  224.         newmaze();
  225.         break;
  226.        case 3:         /* Demo  */
  227.         demomode=TRUE;
  228.         break;
  229.        case 4:         /* Quit  */
  230.         leave("");
  231.        case 5:         /* About */
  232.            ; /* Inserted ; to make Aztec happy -- PDS(1) -- 31-jul-88 */
  233.       }
  234.    }
  235.   }
  236.  }
  237. }
  238.  
  239. void leave(error)
  240. char *error;
  241. {
  242.  BPTR file;
  243.                    /* Free Resouces & Exit */
  244.  if(window)        CloseWindow(window);
  245.  if(screen)        CloseScreen(screen);
  246.  if(IntuitionBase) CloseLibrary(IntuitionBase);
  247.  if(GfxBase)       CloseLibrary(GfxBase);
  248.  if (mymaze)       FreeMem(mymaze,(xsize>>3)*ysize);
  249.  if (raster)       FreeRaster(raster,192,188);
  250.  
  251.  if (*error && WorkBench &&
  252.      (file=Open("con:20/70/400/60/Maze 3D Demo",MODE_OLDFILE)))
  253.  {
  254.   Write(file,error,strlen(error));
  255.   Delay(200L);
  256.   Close(file);
  257.  }
  258.  else if (*error) printf("%s\n",error);
  259.  exit(0);
  260. }
  261.  
  262. void newmaze()
  263. {
  264.  if (mymaze) FreeMem(mymaze,(xsize>>3)*ysize); /* Free old maze */
  265.  xsize=32+mazesize*16;                         /* get new dimension */
  266.  ysize=12+mazesize*12;
  267.  if (!(mymaze=(char*) AllocMem((xsize>>3)*ysize,MEMF_CHIP|MEMF_CLEAR)))
  268.      leave("Out of chip memory");              /* allocate new one */
  269.  SetAPen(rp,6);                                /* clear status display */
  270.  RectFill(rp,205,27,304,110);
  271.  SetAPen(rp,1);
  272.  statusline(10,"Moves:");
  273.  statusline(30,"Looking");
  274.  statusline(60,"Size:");
  275.  sprintf(buffer,"%ld*%ld",xsize,ysize);
  276.  statusline(70,buffer);
  277.  
  278.  maze(xsize,ysize,mymaze);                     /* genarate a new maze */
  279.  seed = FastRand(seed);
  280.  y= ((seed & 0x7ffe) % (ysize-4)+2) & 0x7ffe;  /* random start point */
  281.  x= 2;
  282.  seed = FastRand(seed);
  283.  wayout = ((seed & 0x7ffe) % (ysize-4)+2) & 0x7ffe;  /* random exit */
  284.  MAZESET(xsize-3,wayout,xsize,mymaze);               /* open exit */
  285.  direction=1;                                    /* heading right (east) */
  286.  statusline(40,heading[direction]);
  287.  moves=0;
  288.  show3d();
  289.  showmaze();
  290. }
  291.  
  292. void statusline(y,text)
  293. short y;
  294. char *text;
  295. {                                  /* Write text, centered, into */
  296.  Move(rp,255-strlen(text)*4,27+y); /* status-display */
  297.  SetAPen(rp,1);
  298.  SetBPen(rp,6);
  299.  Text(rp,text,strlen(text));
  300. }
  301.  
  302. void showmaze()                   /* show the maze */
  303. {
  304.  mazeimage.Width=xsize;           /* we define a Image-structure on our */
  305.  mazeimage.Height=ysize;          /* bitmapped maze */
  306.  mazeimage.ImageData=(short*)mymaze;
  307.  DrawImage(rp,&mazeimage,255-(xsize/2),127);
  308.                                                /* wait for a message */
  309.  while(! window->UserPort->mp_MsgList.lh_Head->ln_Succ)
  310.  {
  311.   SetAPen(rp,++i&7);                        /* exit and current position */
  312.   WritePixel(rp,255-(xsize/2)+x,127+y);     /* are blinking */
  313.   WritePixel(rp,253-(xsize/2)+xsize,127+wayout);
  314.   Delay(6L);
  315.  }
  316.  SetAPen(rp,0);
  317.  RectFill(rp,191,127,319,199);
  318. }
  319.  
  320. void show3d()
  321. {
  322.  register short k,inner,outer,wall;
  323.  
  324.  WaitBOVP(rp);          /* doesn't have too much effect in this case */
  325.  for(i=1;i<7;i++)       /* get the wall in front */
  326.   if(!(MAZETEST(x+i*dirincs[direction][0],y+i*dirincs[direction][1],
  327.               xsize,mymaze))) break;
  328.  wall=6-i;
  329.  
  330.  for(k=-1;k < 2;k+=2)   /* draw a 'sky' and a 'floor' */
  331.  {
  332.   SetAPen(rp,(k+8) % 8);
  333.   AreaMove(rp,1,106+k*94);
  334.   AreaDraw(rp,187,106+k*94);
  335.   AreaDraw(rp,94+(2<<wall),106+k*(2<<wall)+k);
  336.   AreaDraw(rp,94-(2<<wall),106+k*(2<<wall)+k);
  337.   AreaEnd(rp);
  338.  }
  339.  
  340.  if(i!=7)
  341.  {
  342.   if(y==wayout && (x+i*dirincs[direction][0])==xsize-1)
  343.   {                        /* are we looking at the exit ? */
  344.    SetAPen(rp,7);
  345.    RectFill(rp,94-(2<<(++wall)),106-(2<<wall),94+(2<<wall),106);
  346.    SetAPen(rp,1);
  347.    RectFill(rp,94-(2<<wall),107,94+(2<<wall),106+(2<<wall));
  348.   }
  349.   else
  350.   {
  351.    SetAPen(rp,5);   /* draw a light grey wall */
  352.    RectFill(rp,94-(2<<wall),106-(2<<wall),94+(2<<wall),106+(2<<wall));
  353.   }
  354.  }
  355.  else        /* the front wall is too far away */
  356.  {
  357.   SetAPen(rp,4);
  358.   AreaMove(rp,92,104);
  359.   AreaDraw(rp,92,108);
  360.   AreaDraw(rp,96,104);
  361.   AreaDraw(rp,96,108);
  362.   AreaEnd(rp);
  363.  }
  364.  
  365.  for(k=-1;k < 2;k+=2)      /* draw walls on the left and on the right */
  366.   for(i=5-wall;i>-1;i--)   /* starting from the front wall ending at */
  367.   {                        /* our current position */
  368.    int xx, yy;        /* Patch to make Aztec happy -- PDS(1) -- 31-jul-88 */
  369.    inner=(2<<(5-i));       /* inner edges of a wall */
  370.    outer=(inner<<1);       /* outer edges */
  371.    if(outer > 94) outer=94;  /* 'Clip' if too large */
  372.                            /* check if a wall or a passage */
  373.    xx=x+dirincs[(direction+k)&3][0]+i*dirincs[direction][0]; /* PDS(1) */
  374.    yy=y+dirincs[(direction+k)&3][1]+i*dirincs[direction][1]; /* PDS(1) */
  375.    if(!(MAZETEST(xx,yy, xsize,mymaze)))
  376.    {                             /* it's a wall */
  377.     SetAPen(rp,4);
  378.     AreaMove(rp,94+k*inner,106-inner);
  379.     AreaDraw(rp,94+k*inner,106+inner);
  380.     AreaDraw(rp,94+k*outer,106+outer);
  381.     AreaDraw(rp,94+k*outer,106-outer);
  382.     AreaEnd(rp);
  383.    }
  384.    else                         /* it's a passage */
  385.    {
  386.     SetAPen(rp,7);              /* clear upper and lower corners */
  387.     AreaMove(rp,94+k*outer,106-outer);
  388.     AreaDraw(rp,94+k*inner,106-inner);
  389.     AreaDraw(rp,94+k*outer,106-inner);
  390.     AreaEnd(rp);
  391.     SetAPen(rp,1);
  392.     AreaMove(rp,94+k*outer,106+outer);
  393.     AreaDraw(rp,94+k*inner,106+inner);
  394.     AreaDraw(rp,94+k*outer,106+inner);
  395.     AreaEnd(rp);
  396.     SetAPen(rp,5);              /* light grey wall */
  397.     if (k==1) RectFill(rp,94+inner,106-inner,94+outer,106+inner);
  398.     else      RectFill(rp,94-outer,106-inner,94-inner,106+inner);
  399.    }
  400.   }
  401. }
  402.  
  403. void demo()    /* demo mode: follow the left-hand wall until we get to */
  404. {              /* the exit */
  405.  long delay;
  406.                /* be fast if the exit is far away, slow if it gets nearer */
  407.  delay=19-18*(xsize-3-x+((wayout-y)<0?-(wayout-y):(wayout-y)))/
  408.           ((wayout<ysize/2? ysize-wayout:wayout)+xsize-3);
  409.  
  410.  if(y==wayout && x==xsize-3) /* did we reach the exit ?*/
  411.  {
  412.   demomode=FALSE;            /* stop if we did */
  413.   return;
  414.  }                           /* is it possible to turn left ? */
  415.  if(MAZETEST(x+dirincs[(direction-1)&3][0],y+dirincs[(direction-1)&3][1],
  416.              xsize,mymaze))
  417.  {
  418.   left();                    /* yes, turn left */
  419.   Delay(delay);
  420.   forward();                 /* and one step forward */
  421.  }
  422.  else if(!forward()) right(); /* if not try to move forward, if everything */
  423.                               /* fails, turn right */
  424.  Delay(delay);
  425. }
  426.  
  427. BOOL forward()                /* move one step forward if possible */
  428. {
  429.  if(!(MAZETEST(x+dirincs[direction][0],
  430.              y+dirincs[direction][1],xsize,mymaze))) return(FALSE);
  431.  
  432.  x+=dirincs[direction][0];
  433.  y+=dirincs[direction][1];
  434.  moves++;
  435.  sprintf(buffer," %ld/%ld ",
  436.          moves,xsize-3-x+((wayout-y)<0?-(wayout-y):(wayout-y)));
  437.  statusline(20,buffer);
  438.  show3d();
  439.  
  440.  if(y==wayout && x==xsize-3)  /* has the exit been reached ?*/
  441.  {
  442.   SetAPen(rp,1);              /* yes, write some stupid text */
  443.   SetBPen(rp,7);
  444.   Move(rp,58,104);
  445.   Text(rp,"Solved in",9);
  446.   SetAPen(rp,6);
  447.   SetBPen(rp,1);
  448.   sprintf(buffer,"%ld moves.",moves);
  449.   Move(rp,94-strlen(buffer)*4,116);
  450.   Text(rp,buffer,strlen(buffer));
  451.  }
  452.  return(TRUE);
  453. }
  454.  
  455. void left()                 /* turn left */
  456. {
  457.  direction=(--direction) & 3;
  458.  show3d();
  459.  statusline(40,heading[direction]);
  460. }
  461.  
  462. void right()                /* turn right */
  463. {
  464.  direction=(++direction) & 3;
  465.  show3d();
  466.  statusline(40,heading[direction]);
  467. }
  468.