xref: /plan9/sys/src/games/sokoban/level.c (revision a7b224503558a0aa961cd3f8978597a7421dac99)
1*a7b22450SDavid du Colombier #include <u.h>
2*a7b22450SDavid du Colombier #include <libc.h>
3*a7b22450SDavid du Colombier #include <bio.h>
4*a7b22450SDavid du Colombier #include <draw.h>
5*a7b22450SDavid du Colombier 
6*a7b22450SDavid du Colombier #include "sokoban.h"
7*a7b22450SDavid du Colombier 
8*a7b22450SDavid du Colombier void
consumeline(Biobuf * b)9*a7b22450SDavid du Colombier consumeline(Biobuf *b)
10*a7b22450SDavid du Colombier {
11*a7b22450SDavid du Colombier 	while(Bgetc(b) != '\n')
12*a7b22450SDavid du Colombier 		;
13*a7b22450SDavid du Colombier }
14*a7b22450SDavid du Colombier 
15*a7b22450SDavid du Colombier /* parse a level file */
16*a7b22450SDavid du Colombier int
loadlevels(char * path)17*a7b22450SDavid du Colombier loadlevels(char *path)
18*a7b22450SDavid du Colombier {
19*a7b22450SDavid du Colombier 	Biobuf *b;
20*a7b22450SDavid du Colombier 	int x = 0, y = 0, lnum = 0;
21*a7b22450SDavid du Colombier 	char c;
22*a7b22450SDavid du Colombier 
23*a7b22450SDavid du Colombier 	if(path == nil)
24*a7b22450SDavid du Colombier 		return 0;
25*a7b22450SDavid du Colombier 
26*a7b22450SDavid du Colombier 	b = Bopen(path, OREAD);
27*a7b22450SDavid du Colombier 	if(b == nil) {
28*a7b22450SDavid du Colombier 		fprint(2, "could not open file %s: %r\n", path);
29*a7b22450SDavid du Colombier 		return 0;
30*a7b22450SDavid du Colombier 	}
31*a7b22450SDavid du Colombier 
32*a7b22450SDavid du Colombier 	memset(levels, 0, Maxlevels*sizeof(Level));
33*a7b22450SDavid du Colombier 
34*a7b22450SDavid du Colombier 	while((c = Bgetc(b)) > 0) {
35*a7b22450SDavid du Colombier 		switch(c)  {
36*a7b22450SDavid du Colombier 		case ';':
37*a7b22450SDavid du Colombier 			consumeline(b); 	/* no ';'-comments in the middle of a level */
38*a7b22450SDavid du Colombier 			break;
39*a7b22450SDavid du Colombier 		case '\n':
40*a7b22450SDavid du Colombier 			levels[lnum].index = lnum;
41*a7b22450SDavid du Colombier 			levels[lnum].done = 0;
42*a7b22450SDavid du Colombier 			x = 0;
43*a7b22450SDavid du Colombier 			levels[lnum].max.y = ++y;
44*a7b22450SDavid du Colombier 
45*a7b22450SDavid du Colombier 			c = Bgetc(b);
46*a7b22450SDavid du Colombier 			if(c == '\n' || c == Beof) {
47*a7b22450SDavid du Colombier 				/* end of level */
48*a7b22450SDavid du Colombier 				if(++lnum == Maxlevels)
49*a7b22450SDavid du Colombier 					goto Done;
50*a7b22450SDavid du Colombier 
51*a7b22450SDavid du Colombier 				x = 0;
52*a7b22450SDavid du Colombier 				y = 0;
53*a7b22450SDavid du Colombier 			} else
54*a7b22450SDavid du Colombier 				Bungetc(b);
55*a7b22450SDavid du Colombier 			break;
56*a7b22450SDavid du Colombier 		case '#':
57*a7b22450SDavid du Colombier 			levels[lnum].board[x][y] = Wall;
58*a7b22450SDavid du Colombier 			x++;
59*a7b22450SDavid du Colombier 			break;
60*a7b22450SDavid du Colombier 		case ' ':
61*a7b22450SDavid du Colombier 			levels[lnum].board[x][y] = Empty;
62*a7b22450SDavid du Colombier 			x++;
63*a7b22450SDavid du Colombier 			break;
64*a7b22450SDavid du Colombier 		case '$':
65*a7b22450SDavid du Colombier 			levels[lnum].board[x][y] = Cargo;
66*a7b22450SDavid du Colombier 			x++;
67*a7b22450SDavid du Colombier 			break;
68*a7b22450SDavid du Colombier 		case '*':
69*a7b22450SDavid du Colombier 			levels[lnum].board[x][y] = GoalCargo;
70*a7b22450SDavid du Colombier 			x++;
71*a7b22450SDavid du Colombier 			break;
72*a7b22450SDavid du Colombier 		case '.':
73*a7b22450SDavid du Colombier 			levels[lnum].board[x][y] = Goal;
74*a7b22450SDavid du Colombier 			x++;
75*a7b22450SDavid du Colombier 			break;
76*a7b22450SDavid du Colombier 		case '@':
77*a7b22450SDavid du Colombier 			levels[lnum].board[x][y] = Empty;
78*a7b22450SDavid du Colombier 			levels[lnum].glenda = Pt(x, y);
79*a7b22450SDavid du Colombier 			x++;
80*a7b22450SDavid du Colombier 			break;
81*a7b22450SDavid du Colombier 		case '+':
82*a7b22450SDavid du Colombier 			levels[lnum].board[x][y] = Goal;
83*a7b22450SDavid du Colombier 			levels[lnum].glenda = Pt(x, y);
84*a7b22450SDavid du Colombier 			x++;
85*a7b22450SDavid du Colombier 			break;
86*a7b22450SDavid du Colombier 		default:
87*a7b22450SDavid du Colombier 			fprint(2, "impossible character for level %d: %c\n", lnum+1, c);
88*a7b22450SDavid du Colombier 			return 0;
89*a7b22450SDavid du Colombier 		}
90*a7b22450SDavid du Colombier 		if(x > levels[lnum].max.x)
91*a7b22450SDavid du Colombier 			levels[lnum].max.x = x;
92*a7b22450SDavid du Colombier 		levels[lnum].max.y = y;
93*a7b22450SDavid du Colombier 	}
94*a7b22450SDavid du Colombier Done:
95*a7b22450SDavid du Colombier 	Bterm(b);
96*a7b22450SDavid du Colombier 
97*a7b22450SDavid du Colombier 	level = levels[0];
98*a7b22450SDavid du Colombier 	numlevels = lnum;
99*a7b22450SDavid du Colombier 
100*a7b22450SDavid du Colombier 	return 1;
101*a7b22450SDavid du Colombier }
102