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