xref: /plan9/sys/src/games/mahjongg/level.c (revision 8fd921c82c91d57a22d5e5497ed27daf3ec44f36)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <draw.h>
5 
6 #include "mahjongg.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
parse(char * layout)17 parse(char *layout)
18 {
19 	int x = 0, y = 0, depth = 0;
20 	char c;
21 	Biobuf *b;
22 
23 	b = Bopen(layout, OREAD);
24 	if(b == nil) {
25 		fprint(2, "could not open file %s: %r\n", layout);
26 		return 0;
27 	}
28 
29 	level.remaining = 0;
30 
31 	while((c = Bgetc(b)) > 0) {
32 		switch(c)  {
33 		case '\n':
34 			x = 0;
35 			y = (y+1) % Ly;
36 			if(!y)
37 				depth++;
38 			break;
39 		case '.':
40 			orig.board[depth][x][y].which = 0;
41 			x++;
42 			break;
43 		case '1':
44 			orig.remaining++;
45 		case '2':
46 		case '3':
47 		case '4':
48 			orig.board[depth][x++][y].which = c-48;
49 			break;
50 		default:
51 			consumeline(b);
52 			break;
53 		}
54 	}
55 	Bterm(b);
56 
57 	return 1;
58 }
59 
60 int
indextype(int type)61 indextype(int type)
62 {
63 	int t;
64 
65 	if(type < 108)
66 		t = (type/36)*Facey * 9 + ((type%36)/4)*Facex;
67 	else if(type < 112)
68 		t = Seasons;
69 	else if(type < 128)
70 		t = 3*Facey + (((type+12)%36)/4)*Facex;
71 	else if(type < 132)
72 		t = Flowers;
73 	else
74 		t = 4*Facey + (((type+28)%36)/4)*Facex;
75 
76 	return t;
77 
78 }
79 
80 Point
indexpt(int type)81 indexpt(int type)
82 {
83 	Point p;
84 
85 	/*
86 	 * the first 108 bricks are 4 of each, 36 per line:
87 	 * 	x = (index%36)/4
88 	 *	y = (index)/36
89 	 * then multiply by the size of a single tile.
90 	 * the next 4 are the seasons, so x = index%4...
91 	 * and so on...
92 	 */
93 
94 	if(type < 108)
95 		p = Pt(((type%36)/4)*Facex, (type/36)*Facey);
96 	else if(type < 112)
97 		p = Pt((type%4)*Facex, 3*Facey);
98 	else if(type < 128)
99 		p = Pt((((type+12)%36)/4)*Facex, 3*Facey);
100 	else if(type < 132)
101 		p = Pt(((type+4)%4)*Facex, 4*Facey);
102 	else
103 		p = Pt((((type+28)%36)/4)*Facex, 4*Facey);
104 	return p;
105 }
106 
107 /* use the seed to generate a replayable game */
108 void
generate(uint seed)109 generate(uint seed)
110 {
111 	int x, y, d, n;
112 	int order[144];
113 	Point p;
114 
115 	srand(seed);
116 
117 	for (x = 0; x < Tiles; x++)
118 		order[x] = x;
119 
120 	for(x = 0; x < Tiles; x++) {
121 		n = order[x];
122 		y = nrand(Tiles);
123 		order[x] = order[y];
124 		order[y] = n;
125 	}
126 
127 	n = 0;
128 	for(d = 0; d < Depth; d++)
129 		for(y = 0; y < Ly; y++)
130 			for(x = 0; x < Lx; x++)
131 				if(orig.board[d][x][y].which == 1) {
132 
133 					orig.board[d][x][y].type = indextype(order[n]);
134 					p = indexpt(order[n++]);
135 					orig.board[d][x][y].start = p;
136 					orig.board[d][x+1][y].start = p;
137 					orig.board[d][x][y+1].start = p;
138 					orig.board[d][x+1][y+1].start = p;
139 				}
140 
141 	if(n != orig.remaining)
142 		fprint(2, "level improperly generated: %d elements, "
143 			"should have %d\n", n, orig.remaining);
144 
145 	orig.c = NC;
146 	orig.l = NC;
147 	orig.done = 0;
148 	level = orig;
149 }
150