]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/mahjongg/graphics.c
devcons: fix permissions for reboot and sysstat
[plan9front.git] / sys / src / games / mahjongg / graphics.c
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <event.h>
5
6 #include "mahjongg.h"
7
8
9 /*
10  * mark tiles that partially obscure the given tile.
11  * relies on Depth*Dxy <= Tilex/2
12  */
13 void
14 markabove(int d, int x, int y)
15 {
16         int dx, dy;
17
18         for(d++; d < Depth; d++)
19                 for(dx = -1; dx <= 2; dx++)
20                         for(dy = -1; dy <= 2; dy++)
21                                 if(x+dx < Lx && x+dx >= 0 &&
22                                     y+dy < Ly && y+dy >= 0)
23                                         level.board[d][x+dx][y+dy].redraw = 1;
24 }
25
26 void
27 markbelow(int d, int x, int y)
28 {
29         int dx, dy;
30
31         for(d--; d >= 0; d--)
32                 for(dx = -2; dx <= 1; dx++)
33                         for(dy = -2; dy <= 1; dy++)
34                                 if(x+dx < Lx && x+dx >= 0 &&
35                                     y+dy < Ly && y+dy >= 0)
36                                         level.board[d][x+dx][y+dy].redraw = 1;
37 }
38
39 Rectangle
40 tilerect(Click c)
41 {
42         Point p;
43         Rectangle r;
44
45         p = Pt(c.x*(Facex/2)-(c.d*TileDxy), c.y*(Facey/2)-(c.d*TileDxy));
46         r = Rpt(p, addpt(p, Pt(Facex, Facey)));
47         return rectaddpt(r, Pt(Depth*TileDxy, Depth*TileDxy));
48 }
49
50 void
51 clearbrick(Click c)
52 {
53         Rectangle r;
54
55         level.hist[--level.remaining] = c;
56
57         level.board[c.d][c.x][c.y].which = None;
58         level.board[c.d][c.x+1][c.y].which = None;
59         level.board[c.d][c.x][c.y+1].which = None;
60         level.board[c.d][c.x+1][c.y+1].which = None;
61
62         r = tilerect(c);
63         draw(img, r, background, nil, r.min);
64
65         markabove(c.d, c.x, c.y);
66         markbelow(c.d, c.x, c.y);
67 }
68
69 void
70 drawbrick(Click c)
71 {
72         Rectangle r;
73
74         r = tilerect(c);
75         draw(img, r, tileset, nil, level.board[c.d][c.x][c.y].start);
76
77         if(level.board[c.d][c.x][c.y].clicked)
78                 draw(img, r, selected, nil, ZP);
79
80         if(eqcl(level.l, c))
81                 border(img, r, 2, litbrdr, level.board[c.d][c.x][c.y].start);
82
83         /* looks better without borders, uncomment to check it out with'em */
84 //      r = Rpt(r.min, addpt(r.min, Pt(Tilex, Tiley)));
85 //      draw(img, r, brdr, nil, ZP);
86 }
87
88 void
89 redrawlevel(int all)
90 {
91         Brick *b;
92         int d, x, y;
93
94         for(d = 0; d < Depth; d++)
95                 for(y = 0; y < Ly; y++)
96                         for(x = 0; x < Lx; x++) {
97                                 b = &level.board[d][x][y];
98                                 if(b->which == TL && (all || b->redraw)) {
99                                         drawbrick(Cl(d,x,y));
100                                         markabove(d,x,y);
101                                 }
102                                 b->redraw = 0;
103                         }
104
105         draw(screen, screen->r, img, nil, ZP);
106         flushimage(display, 1);
107 }
108
109 void
110 updatelevel(void)
111 {
112         redrawlevel(0);
113 }
114
115 void
116 drawlevel(void)
117 {
118         draw(img, img->r, background, nil, ZP);
119         redrawlevel(1);
120 }
121
122 void
123 resize(Point p)
124 {
125         int fd;
126
127         fd = open("/dev/wctl", OWRITE);
128         if(fd >= 0){
129                 fprint(fd, "resize -dx %d -dy %d", p.x, p.y);
130                 close(fd);
131         }
132 }
133
134 void
135 hint(void)
136 {
137         int d = 0, x = 0, y = 0;
138         Brick *a, *b = nil;
139
140         if(level.c.d != -1) {
141                 if((b = bmatch(level.c)) != nil) {
142                         d = level.c.d;
143                         x = level.c.x;
144                         y = level.c.y;
145                 }
146         } else 
147                 for(d = Depth - 1; d >= 0; d--)
148                         for(y = 0; y < Ly; y++)
149                                 for(x = 0; x < Lx; x++)
150                                         if(level.board[d][x][y].which == TL &&
151                                             isfree(Cl(d,x,y)) &&
152                                             (b = bmatch(Cl(d,x,y))) != nil)
153                                                 goto Matched;
154 Matched:
155         if (b == nil)
156                 return;
157
158         a = &level.board[d][x][y];
159         a->clicked = 1;
160         a->redraw = 1;
161         b->clicked = 1;
162         b->redraw = 1;
163         updatelevel();
164         sleep(100);
165         if(level.c.d == -1){
166                 a->clicked = 0;
167                 a->redraw = 1;
168         }
169         b->clicked = 0;
170         b->redraw = 1;
171         updatelevel();
172         sleep(100);
173         a->clicked = 1;
174         a->redraw = 1;
175         b->clicked = 1;
176         b->redraw = 1;
177         updatelevel();
178         sleep(100);
179         if(level.c.d == -1){
180                 a->clicked = 0;
181                 a->redraw = 1;
182         }
183         b->clicked = 0;
184         b->redraw = 1;
185         updatelevel();
186 }
187
188 void
189 done(void)
190 {
191         level.done = 1;
192         draw(screen, screen->r, selected, gameover, ZP);
193         flushimage(display, 1);
194 }
195
196 Click
197 findclick(Point coord)
198 {
199         Click c;
200
201         for(c.d = Depth - 1; c.d >= 0; c.d--) {
202                 c.x = (coord.x + TileDxy*c.d)/(Facex/2);
203                 c.y = (coord.y + TileDxy*c.d)/(Facey/2);
204                 switch(level.board[c.d][c.x][c.y].which) {
205                 case None:
206                         break;
207                 case TL:
208                         return c;
209                 case TR:
210                         c.x = c.x - 1;
211                         return c;
212                 case BR:
213                         c.x = c.x - 1;
214                         c.y = c.y - 1;
215                         return c;
216                 case BL:
217                         c.y = c.y - 1;
218                         return c;
219                 }
220         }
221         return NC;
222 }
223
224 void
225 clicked(Point coord)
226 {
227         Click c;
228         Brick *b, *bc;
229
230         c = findclick(coord);
231         if (c.d == -1)
232                 return;
233
234         b = &level.board[c.d][c.x][c.y];
235         if(isfree(c)) {
236                 if(level.c.d == -1) {
237                         level.c = c;
238                         b->clicked = 1;
239                         b->redraw = 1;
240                 } else if(eqcl(c, level.c)) {
241                         level.c = NC;
242                         b->clicked = 0;
243                         b->redraw = 1;
244                 } else {
245                         bc = &level.board[level.c.d][level.c.x][level.c.y];
246                         if(b->type == bc->type) {
247                                 clearbrick(c);
248                                 bc->clicked = 0;
249                                 clearbrick(level.c);
250                                 level.c = NC;
251                         } else {
252                                 bc->clicked = 0;
253                                 bc->redraw = 1;
254                                 b->clicked = 1;
255                                 b->redraw = 1;
256                                 level.c = c;
257                         }
258                 }
259                 updatelevel();
260                 if(!canmove())
261                         done();
262         }
263 }
264
265 void
266 undo(void)
267 {
268         int i, j, d, x, y;
269
270         if(level.remaining >= Tiles)
271                 return;
272
273         for(i=1; i<=2; i++) {
274                 j = level.remaining++;
275                 d = level.hist[j].d;
276                 x = level.hist[j].x;
277                 y = level.hist[j].y;
278                 level.board[d][x][y].which = TL;
279                 level.board[d][x+1][y].which = TR;
280                 level.board[d][x+1][y+1].which = BR;
281                 level.board[d][x][y+1].which = BL;
282                 level.board[d][x][y].redraw = 1;
283         }
284         updatelevel();
285 }
286
287 void
288 deselect(void)
289 {
290         Brick *b;
291
292         if(level.c.d == -1)
293                 return;
294         b = &level.board[level.c.d][level.c.x][level.c.y];
295         level.c = NC;
296         b->clicked = 0;
297         b->redraw = 1;
298         updatelevel();
299 }
300
301 void
302 light(Point coord)
303 {
304         Click c = findclick(coord);
305         if (c.d == -1)
306                 return;
307
308         if(eqcl(level.l, c))
309                 return;
310
311         if (level.l.d != -1) {
312                 level.board[level.l.d][level.l.x][level.l.y].redraw = 1;
313                 level.l = NC;
314         }
315
316         if(isfree(c)) {
317                 level.l = c;
318                 level.board[c.d][c.x][c.y].redraw = 1;
319         }
320
321         updatelevel();
322 }
323
324 void
325 clearlevel(void)
326 {
327         Click c, cm;
328
329         for(c.d = Depth - 1; c.d >= 0; c.d--)
330                 for(c.y = 0; c.y < Ly; c.y++)
331                         for(c.x = 0; c.x < Lx; c.x++)
332                                 if(level.board[c.d][c.x][c.y].which == TL &&
333                                     isfree(c)) {
334                                         cm = cmatch(c, c.d);
335                                         if(cm.d != -1) {
336                                                 clearbrick(cm);
337                                                 clearbrick(c);
338                                                 updatelevel();
339                                                 clearlevel();
340                                         }
341                                 }
342 }