#include <u.h>
#include <libc.h>
#include <bio.h>
#include <draw.h>
#include "rushhour.h"
static char buf[1024];
static void
consumeline(Biobuf *b)
{
while(Bgetc(b) != '\n')
;
}
static char*
readline(Biobuf *b)
{
char *p, *e;
int c;
p = buf;
e = buf + sizeof(buf) - 1; /* -1 for final \n */
while((c = Bgetc(b)) != '\n' )
if (p < e)
*(p++) = c;
*p = '\0';
return buf;
}
static void
setlevel(int lnum, int x, int y, int e)
{
levels[lnum].board[x][y] = e;
if (levels[lnum].length[e] == 0)
levels[lnum].orient[e] = -1 - y;
else if (levels[lnum].orient[e] < 0)
if (levels[lnum].orient[e] == -1 -y)
levels[lnum].orient[e] = OHoriz;
else
levels[lnum].orient[e] = OVert;
levels[lnum].length[e]++;
switch(e) {
case CarX:
if (levels[lnum].us == Empty)
levels[lnum].us = e;
break;
case CarY:
if (levels[lnum].us == Empty)
levels[lnum].us = e;
break;
case CarZ:
if (levels[lnum].us == Empty || levels[lnum].us == CarX)
levels[lnum].us = e;
break;
}
}
/* parse a level file */
int
loadlevels(char *path)
{
Biobuf *b;
int x, y, lnum, i;
char c;
if(path == nil)
return -1;
b = Bopen(path, OREAD);
if(b == nil) {
fprint(2, "cannot load levels: %r\n");
return -1;
}
for (i=0; i < numlevels; i++)
free(levels[i].name);
memset(levels, 0, Maxlevels*sizeof(Level));
x = Off;
y = Off;
lnum = 0;
while((c = Bgetc(b)) > 0) {
switch(c) {
case ';':
consumeline(b);
break;
case ':':
levels[lnum].name = estrdup(readline(b)); /* at most one name for a level */
break;
case '\n':
levels[lnum].index = lnum;
levels[lnum].done = 0;
x = Off;
y++;
levels[lnum].max.y = y;
c = Bgetc(b);
if(c == '\n' || c == Beof) {
/* end of level */
if(++lnum == Maxlevels)
goto Done;
x = Off;
y = Off;
levels[lnum].win = Pt(Off,Off);
} else
Bungetc(b);
break;
case '#':
levels[lnum].board[x][y] = Wall;
x++;
break;
case '.':
case '@': /* used to be goal (exit); need no longer be specially marked */
levels[lnum].board[x][y] = Empty;
x++;
break;
case 'x':
setlevel(lnum, x, y, CarX);
x++;
break;
case 'y':
setlevel(lnum, x, y, CarY);
x++;
break;
case 'z':
setlevel(lnum, x, y, CarZ);
x++;
break;
case 'a':
setlevel(lnum, x, y, CarA);
x++;
break;
case 'b':
setlevel(lnum, x, y, CarB);
x++;
break;
case 'c':
setlevel(lnum, x, y, CarC);
x++;
break;
case 'd':
setlevel(lnum, x, y, CarD);
x++;
break;
case 'e':
setlevel(lnum, x, y, CarE);
x++;
break;
case 'f':
setlevel(lnum, x, y, CarF);
x++;
break;
case 'g':
setlevel(lnum, x, y, CarG);
x++;
break;
case 'h':
setlevel(lnum, x, y, CarH);
x++;
break;
case 'i':
setlevel(lnum, x, y, CarI);
x++;
break;
case 'j':
setlevel(lnum, x, y, CarJ);
x++;
break;
case 'k':
setlevel(lnum, x, y, CarK);
x++;
break;
case 'l':
setlevel(lnum, x, y, CarL);
x++;
break;
case 'm':
setlevel(lnum, x, y, CarM);
x++;
break;
case 'n':
setlevel(lnum, x, y, CarN);
x++;
break;
case 'o':
setlevel(lnum, x, y, TruckO);
x++;
break;
case 'p':
setlevel(lnum, x, y, TruckP);
x++;
break;
case 'q':
setlevel(lnum, x, y, TruckQ);
x++;
break;
case 'r':
setlevel(lnum, x, y, TruckR);
x++;
break;
case 's':
setlevel(lnum, x, y, TruckS);
x++;
break;
case 't':
setlevel(lnum, x, y, TruckT);
x++;
break;
case 'u':
setlevel(lnum, x, y, TruckU);
x++;
break;
case 'v':
setlevel(lnum, x, y, TruckV);
x++;
break;
default:
fprint(2, "impossible character for level %d: %c\n", lnum+1, c);
return -1;
}
if(x > levels[lnum].max.x)
levels[lnum].max.x = x;
levels[lnum].max.y = y;
}
Done:
Bterm(b);
level = levels[0];
numlevels = lnum;
return lnum;
}
|