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