|
@@ -0,0 +1,310 @@
|
|
|
|
+#include <u.h>
|
|
|
|
+#include <libc.h>
|
|
|
|
+#include <draw.h>
|
|
|
|
+#include <event.h>
|
|
|
|
+
|
|
|
|
+#include "mahjongg.h"
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+freeup(int d, Point p)
|
|
|
|
+{
|
|
|
|
+ /* are we blocked from above? */
|
|
|
|
+ if(d == Depth -1 || (level.board[d+1][p.x][p.y].which == 0 &&
|
|
|
|
+ level.board[d+1][p.x+1][p.y].which == 0 &&
|
|
|
|
+ level.board[d+1][p.x][p.y+1].which == 0 &&
|
|
|
|
+ level.board[d+1][p.x+1][p.y+1].which == 0))
|
|
|
|
+ return 1;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+freeleft(int d, Point p)
|
|
|
|
+{
|
|
|
|
+
|
|
|
|
+ /* blocked from the left? */
|
|
|
|
+ if(p.x == 0 || (level.board[d][p.x-1][p.y].which == 0 &&
|
|
|
|
+ level.board[d][p.x-1][p.y+1].which == 0))
|
|
|
|
+ return 1;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+freeright(int d, Point p)
|
|
|
|
+{
|
|
|
|
+ if(p.x == Lx-2 || (level.board[d][p.x+2][p.y].which == 0 &&
|
|
|
|
+ level.board[d][p.x+2][p.y+1].which == 0))
|
|
|
|
+ return 1;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+isfree(int d, Point p)
|
|
|
|
+{
|
|
|
|
+ return (freeleft(d, p) || freeright(d, p)) && freeup(d, p);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+clearbrick(int d, Point p)
|
|
|
|
+{
|
|
|
|
+ level.board[d][p.x][p.y].which = 0;
|
|
|
|
+ level.board[d][p.x+1][p.y].which = 0;
|
|
|
|
+ level.board[d][p.x][p.y+1].which = 0;
|
|
|
|
+ level.board[d][p.x+1][p.y+1].which = 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+resize(Point p)
|
|
|
|
+{
|
|
|
|
+ /* resize to the size of the current level */
|
|
|
|
+
|
|
|
|
+ int fd;
|
|
|
|
+
|
|
|
|
+ fd = open("/dev/wctl", OWRITE);
|
|
|
|
+ if(fd >= 0){
|
|
|
|
+ fprint(fd, "resize -dx %d -dy %d", p.x, p.y);
|
|
|
|
+ close(fd);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+drawbrick(int d, int x, int y)
|
|
|
|
+{
|
|
|
|
+ Point p;
|
|
|
|
+ Rectangle r;
|
|
|
|
+
|
|
|
|
+ p = Pt(x*(Facex/2)-(d*TileDxy), y*(Facey/2)-(d*TileDxy));
|
|
|
|
+ r = Rpt(p, addpt(p, Pt(Facex, Facey)));
|
|
|
|
+ r = rectaddpt(r, Pt(Depth*TileDxy, Depth*TileDxy));
|
|
|
|
+ draw(img, r, tileset, nil, level.board[d][x][y].start);
|
|
|
|
+
|
|
|
|
+ if(level.board[d][x][y].clicked)
|
|
|
|
+ draw(img, r, selected, nil, ZP);
|
|
|
|
+
|
|
|
|
+ /* looks better without borders, uncomment to check it out with'em */
|
|
|
|
+// r = Rpt(r.min, addpt(r.min, Pt(Tilex, Tiley)));
|
|
|
|
+// draw(img, r, brdr, nil, ZP);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+drawlevel(void)
|
|
|
|
+{
|
|
|
|
+ int d, x, y;
|
|
|
|
+
|
|
|
|
+ draw(img, img->r, background, nil, ZP);
|
|
|
|
+
|
|
|
|
+ for(d = 0; d < Depth; d++)
|
|
|
|
+ for(y = 0; y < Ly; y++)
|
|
|
|
+ for(x = 0; x < Lx; x++)
|
|
|
|
+ if(level.board[d][x][y].which == 1)
|
|
|
|
+ drawbrick(d, x, y);
|
|
|
|
+
|
|
|
|
+ draw(screen, screen->r, img, nil, ZP);
|
|
|
|
+ flushimage(display, 1);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+Brick *
|
|
|
|
+bmatch(int d, Point p)
|
|
|
|
+{
|
|
|
|
+ int x, y;
|
|
|
|
+ int ld = d;
|
|
|
|
+
|
|
|
|
+ do {
|
|
|
|
+ for(y = 0; y < Ly; y++)
|
|
|
|
+ for(x = 0; x < Lx; x++)
|
|
|
|
+ if(level.board[ld][x][y].which == 1 && isfree(ld, Pt(x, y)) && !eqpt(Pt(x, y), p) &&
|
|
|
|
+ level.board[d][p.x][p.y].type == level.board[ld][x][y].type)
|
|
|
|
+
|
|
|
|
+ return &level.board[ld][x][y];
|
|
|
|
+
|
|
|
|
+ } while(--ld >= 0);
|
|
|
|
+
|
|
|
|
+ return nil;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+canmove(void)
|
|
|
|
+{
|
|
|
|
+ int d, x, y;
|
|
|
|
+
|
|
|
|
+ for(d = Depth - 1; d >= 0; d--)
|
|
|
|
+ for(y = 0; y < Ly; y++)
|
|
|
|
+ for(x = 0; x < Lx; x++)
|
|
|
|
+ if(level.board[d][x][y].which == 1 && isfree(d, Pt(x, y)))
|
|
|
|
+ if(bmatch(d, Pt(x, y)) != nil)
|
|
|
|
+ return 1;
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+hint(void)
|
|
|
|
+{
|
|
|
|
+ Brick *b = nil;
|
|
|
|
+ int d = 0, x = 0, y = 0;
|
|
|
|
+
|
|
|
|
+ if(level.c.d != -1) {
|
|
|
|
+ if((b = bmatch(level.c.d, level.c.p)) != nil) {
|
|
|
|
+ d = level.c.d;
|
|
|
|
+ x = level.c.p.x;
|
|
|
|
+ y = level.c.p.y;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ for(d = Depth - 1; d >= 0; d--)
|
|
|
|
+ for(y = 0; y < Ly; y++)
|
|
|
|
+ for(x = 0; x < Lx; x++)
|
|
|
|
+ if(level.board[d][x][y].which == 1 && isfree(d, Pt(x, y)))
|
|
|
|
+ if((b = bmatch(d, Pt(x, y))) != nil)
|
|
|
|
+ goto Matched;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+Matched:
|
|
|
|
+ if(b != nil) {
|
|
|
|
+ level.board[d][x][y].clicked = 1;
|
|
|
|
+ b->clicked = 1;
|
|
|
|
+ drawlevel();
|
|
|
|
+ sleep(500);
|
|
|
|
+ if(level.c.d == -1)
|
|
|
|
+ level.board[d][x][y].clicked = 0;
|
|
|
|
+ b->clicked = 0;
|
|
|
|
+ drawlevel();
|
|
|
|
+ sleep(500);
|
|
|
|
+ level.board[d][x][y].clicked = 1;
|
|
|
|
+ b->clicked = 1;
|
|
|
|
+ drawlevel();
|
|
|
|
+ sleep(500);
|
|
|
|
+ if(level.c.d == -1)
|
|
|
|
+ level.board[d][x][y].clicked = 0;
|
|
|
|
+ b->clicked = 0;
|
|
|
|
+ drawlevel();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+done(void)
|
|
|
|
+{
|
|
|
|
+ level.done = 1;
|
|
|
|
+ draw(screen, screen->r, selected, gameover, ZP);
|
|
|
|
+ draw(screen, screen->r, selected, gameover, ZP);
|
|
|
|
+ flushimage(display, 1);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+clicked(Point coord)
|
|
|
|
+{
|
|
|
|
+ Point p;
|
|
|
|
+ int d;
|
|
|
|
+
|
|
|
|
+ /* ugly on purpose */
|
|
|
|
+
|
|
|
|
+ for(d = Depth - 1; d >= 0; d--) {
|
|
|
|
+ p = Pt((coord.x + TileDxy*d)/(Facex/2), (coord.y + TileDxy*d)/(Facey/2));
|
|
|
|
+ switch(level.board[d][p.x][p.y].which) {
|
|
|
|
+ case 0:
|
|
|
|
+ break;
|
|
|
|
+ case 1:
|
|
|
|
+ goto Found;
|
|
|
|
+ case 2:
|
|
|
|
+ p = Pt(p.x-1, p.y);
|
|
|
|
+ goto Found;
|
|
|
|
+ case 3:
|
|
|
|
+ p = Pt(p.x-1, p.y-1);
|
|
|
|
+ goto Found;
|
|
|
|
+ case 4:
|
|
|
|
+ p = Pt(p.x, p.y-1);
|
|
|
|
+ goto Found;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+Found:
|
|
|
|
+ if(freeup(d, p) && (freeleft(d, p) || freeright(d, p))) {
|
|
|
|
+ if(level.c.d == -1) {
|
|
|
|
+ level.c.d = d;
|
|
|
|
+ level.c.p = p;
|
|
|
|
+ level.board[d][p.x][p.y].clicked = 1;
|
|
|
|
+ } else if(!eqpt(p, level.c.p) &&
|
|
|
|
+ (level.board[d][p.x][p.y].type == level.board[level.c.d][level.c.p.x][level.c.p.y].type)) {
|
|
|
|
+
|
|
|
|
+ clearbrick(d, p);
|
|
|
|
+ clearbrick(level.c.d, level.c.p);
|
|
|
|
+
|
|
|
|
+ level.c.d = -1;
|
|
|
|
+ level.c.p = Pt(0, 0);
|
|
|
|
+
|
|
|
|
+ level.remaining -= 2;
|
|
|
|
+ } else {
|
|
|
|
+ level.board[d][p.x][p.y].clicked = 0;
|
|
|
|
+ level.board[level.c.d][level.c.p.x][level.c.p.y].clicked = 0;
|
|
|
|
+ level.c.d = -1;
|
|
|
|
+ level.c.p = Pt(0, 0);
|
|
|
|
+ }
|
|
|
|
+ drawlevel();
|
|
|
|
+ if(!canmove())
|
|
|
|
+ done();
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* below only for testing */
|
|
|
|
+
|
|
|
|
+Point
|
|
|
|
+pmatch(int d, Point p)
|
|
|
|
+{
|
|
|
|
+ int x, y;
|
|
|
|
+ int ld = d;
|
|
|
|
+
|
|
|
|
+ do {
|
|
|
|
+ for(y = 0; y < Ly; y++)
|
|
|
|
+ for(x = 0; x < Lx; x++)
|
|
|
|
+ if(level.board[ld][x][y].which == 1 && isfree(ld, Pt(x, y)) && !eqpt(Pt(x, y), p) &&
|
|
|
|
+ level.board[d][p.x][p.y].type == level.board[ld][x][y].type)
|
|
|
|
+
|
|
|
|
+ return Pt(x, y);
|
|
|
|
+
|
|
|
|
+ } while(--ld >= 0);
|
|
|
|
+
|
|
|
|
+ return Pt(-1, -1);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+dmatch(int d, Point p)
|
|
|
|
+{
|
|
|
|
+ int x, y;
|
|
|
|
+ int ld = d;
|
|
|
|
+
|
|
|
|
+ do {
|
|
|
|
+ for(y = 0; y < Ly; y++)
|
|
|
|
+ for(x = 0; x < Lx; x++)
|
|
|
|
+ if(level.board[ld][x][y].which == 1 && isfree(ld, Pt(x, y)) && !eqpt(Pt(x, y), p) &&
|
|
|
|
+ level.board[d][p.x][p.y].type == level.board[ld][x][y].type)
|
|
|
|
+
|
|
|
|
+ return ld;
|
|
|
|
+
|
|
|
|
+ } while(--ld >= 0);
|
|
|
|
+
|
|
|
|
+ return -1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+clearlevel(void)
|
|
|
|
+{
|
|
|
|
+ int d, x, y;
|
|
|
|
+
|
|
|
|
+ for(d = Depth - 1; d >= 0; d--)
|
|
|
|
+ for(y = 0; y < Ly; y++)
|
|
|
|
+ for(x = 0; x < Lx; x++)
|
|
|
|
+ if(level.board[d][x][y].which == 1 && isfree(d, Pt(x, y)))
|
|
|
|
+ if(bmatch(d, Pt(x, y)) != nil) {
|
|
|
|
+ clearbrick(dmatch(d, Pt(x, y)), pmatch(d, Pt(x, y)));
|
|
|
|
+ clearbrick(d, Pt(x, y));
|
|
|
|
+ level.remaining -= 2;
|
|
|
|
+ drawlevel();
|
|
|
|
+ clearlevel();
|
|
|
|
+ }
|
|
|
|
+}
|