Build an engine for a maze game
C99, 771 characters



#include &lt;ncurses.h&gt;
#include &lt;string.h&gt;
#define MIN(A,B) (A&lt;B?A:B)
#define MAX(A,B) (A&gt;B?A:B)
#define T(C,X,Y) case C:if((m[x+X][y+Y]==' ')||(m[x+X][y+Y]=='#'))x+=X,y+=Y;s++;break;
char m[24][81],M[24][81];int i,j,I=0,J,x,y,s=0;
int main(int c,char**v){FILE*f=fopen(v[1],"r");
for(I=0;fgets(m[I],80,f);I++)J=MAX(J,strlen(m[I]));
J--;f=fopen("/dev/random","r");do{x=fgetc(f)%I;y=fgetc(f)%J;}
while(m[x][y]!=' ');initscr();curs_set(0);do{
switch(c){T('e',0,1)T('n',-1,0)T('s',1,0)T('w',0,-1)}
for(i=MAX(0,x-1);i&lt;MIN(x+2,I);i++)for(j=MAX(0,y-1);j&lt;MIN(y+2,J);j++)M[i][j]=1;
for(i=0;i&lt;I;i++)for(j=0;j&lt;J;j++)mvaddch(i,j,M[i][j]?m[i][j]:'?');
mvaddch(x,y,'@');refresh();}while((m[x][y]!='#')&amp;&amp;(c=getch())!='q');
if(m[x][y]=='#')mvprintw(I,0,"Finished in %d steps!",s),getch();endwin();}


Requires and makes use of ncurses. Only one macroization for length, and the N and M macros are to replace the missing minimum and maximum opperators, and I don't think there is much more to do on that.

It assumes the input maze does not exceed 80 characters wide, and that the a maze filename has been passed on the command-line, and that the number of parameters is low enough that the initial value of c isn't a movement command.


Deviates from the standard in that it takes single character direction commands as the lowercase first letter of the ones suggested.
Does show unknown regions as '?'s.


More readable with comments:

#include &lt;ncurses.h&gt;
#include &lt;string.h&gt;

#define MIN(A,B) (A&lt;B?A:B)/*unsafe,but short*/
#define MAX(A,B) (A&gt;B?A:B)/*unsafe,but short*/
// #define MAX(A,B) ((_A=A)&gt;(_B=B)?_A:_B) /* safe but verbose */
#define T(C,X,Y) case C:if((m[x+X][y+Y]==' ')||(m[x+X][y+Y]=='#'))x+=X,y+=Y;s++;break;
char m[24][81],M[24][81];/* [m]ap and [M]ask; NB:mask intialized by default */
int i,j, /* loop indicies over the map */
  I=0,J, /* limits of the map */
  x,y,   /* player position */
  s=0;   /* steps taken */
int main(int c,char**v){
  FILE*f=fopen(v[1],"r"); /* fragile, assumes that the argument is present */
  /* Read the input file */
  for(I=0;fgets(m[I],80,f);I++)J=MAX(J,strlen(m[I])); /* Read in the map */ 
  J--;
  /* note that I leak a file handle here */
  f=fopen("/dev/random","r");
  /* Find a open starting square */
  do{ 
    x=fgetc(f)%I; /* Poor numeric properties, but good enough for code golf */
    y=fgetc(f)%J;
  } while(m[x][y]!=' ');
  /* setup curses */
  initscr(); /* start curses */
  //  raw();     /* WARNING! intercepts C-c, C-s, C-z, etc...
  //          * but shorter than cbreak() 
  //          */
  curs_set(0); /* make the cursor invisible */
  /* main loop */
  do {
    switch(c){
      T('e',0,1)
      T('n',-1,0)
      T('s',1,0)
      T('w',0,-1)
    }
    /* Update the mask */
    for(i=MAX(0,x-1);i&lt;MIN(x+2,I);i++)
      for(j=MAX(0,y-1);j&lt;MIN(y+2,J);j++)
    M[i][j]=1;
    /* draw the maze as masked */
    for(i=0;i&lt;I;i++)
      for(j=0;j&lt;J;j++)
    mvaddch(i,j,M[i][j]?m[i][j]:'?');
    /* draw the player figure */
    mvaddch(x,y,'@');
    refresh(); /* Refresh the display */
  } while((m[x][y]!='#')&amp;&amp;(c=getch())!='q');
  if(m[x][y]=='#')mvprintw(I,0,"Finished in %d steps!",s),getch();
  endwin();
}