shithub: riscv

ref: 4d69aacea023546a7150d92e147e531c38de822f
dir: /sys/src/games/mahjongg/mahjongg.c/

View raw version
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.h>
#include <stdio.h>
#include "mahjongg.h"

#define MJDIR "/sys/games/lib/mahjongg/"

char *Border	= MJDIR "images/border.bit";
char *Mask	= MJDIR "images/mask.bit";
char *Gameover	= MJDIR "images/gameover.bit";

char *deftileset= MJDIR "tilesets/default.tileset";
char *defbackgr = MJDIR "backgrounds/default.bit";
char *deflayout = MJDIR "layouts/default.layout";

ulong defchan;
int trace;

char *buttons[] =
{
	"deselect",
	"new",
	"restart",
	"resize",
	"exit",
	0
};

Menu menu =
{
	buttons
};

void
usage(void)
{
	fprint(2, "usage: %s [-cf] [-b bg] [-l layout] [-t tileset]\n", argv0);
	exits("usage");
}

Image *
eallocimage(Rectangle r, int repl, uint chan, uint color)
{
	Image *tmp;

	tmp = allocimage(display, r, chan, repl, color);
	if(tmp == nil)
		sysfatal("cannot allocate buffer image: %r");
	return tmp;
}

Image *
eloadfile(char *path)
{
	Image *img;
	int fd;

	fd = open(path, OREAD);
	if(fd < 0) {
		fprint(2, "cannot open image file %s: %r\n", path);
		exits("image");
	}
	img = readimage(display, fd, 0);
	if(img == nil)
		sysfatal("cannot load image: %r");
	close(fd);

	return img;
}

void
allocimages(void)
{
	Rectangle one = Rect(0, 0, 1, 1);

	selected = eallocimage(one, 1, RGBA32, setalpha(DPalebluegreen, 0x5f));
	litbrdr = eallocimage(one, 1, RGBA32, DGreen);
	img = eallocimage(Rect(0, 0, Sizex, Sizey), 0,
		defchan? defchan: screen->chan, DBlack);
	textcol = eallocimage(one, 1, RGBA32, DWhite);

	background = eloadfile(defbackgr);
	replclipr(background, 1, img->r);

	mask = eloadfile(Mask);
	gameover = eloadfile(Gameover);
	tileset = eloadfile(deftileset);
}


void
eresized(int new)
{
	if(new && getwindow(display, Refnone) < 0)
		sysfatal("can't reattach to window");
	drawlevel();
}

void
main(int argc, char **argv)
{
	int clickety = 0;
	Mouse m;
	Event e;
	Point origin = Pt(Bord, Bord);

	ARGBEGIN{
	case 'b':
		defbackgr = EARGF(usage());
		break;
	case 'c':
		defchan = RGBA32;
		break;
	case 'f':
		trace = 1;
		break;
	case 'l':
		deflayout = EARGF(usage());
		break;
	case 't':
		deftileset = EARGF(usage());
		break;
	default:
		usage();
	}ARGEND

	if(argc > 0)
		usage();

	if(! parse(deflayout)) {
		fprint(2, "usage: %s [levelfile]\n", argv[0]);
		exits("usage");
	}

	if(initdraw(nil, nil, "mahjongg") < 0)
		sysfatal("initdraw failed: %r");
	einit(Emouse|Ekeyboard);

	allocimages();

	/* resize to the size of the current level */
	resize(img->r.max);

	generate(time(0));
	drawlevel();
	for(;;) {
		if(level.remaining == 0 && !level.done)
			done();
		switch(event(&e)) {
		case Emouse:
			m = e.mouse;
			if(m.buttons&1) {
				if(level.done)
					break;
				if(!clickety && level.remaining > 0) {
					clickety = 1;
					clicked(subpt(m.xy, addpt(screen->r.min,
						origin)));
				}
			} else {
				clickety = 0;
				if(trace)
					light(subpt(m.xy, addpt(screen->r.min,
						origin)));
			}
			if(m.buttons&2) {
				/* nothing here for the moment */
			}
			if(m.buttons&4)
				switch(emenuhit(3, &m, &menu)) {
				case 0:
					deselect();
					break;
				case 1:
					generate(time(0));
					drawlevel();
					break;
				case 2:
					level = orig;
					drawlevel();
					break;
				case 3:
					resize(img->r.max);
					break;
				case 4:
					exits(nil);
				}
			break;
		case 2:
			switch(e.kbdc) {
			case 127:
			case 'q':
			case 'Q':
				exits(nil);
			case 'h':
			case 'H':
				if(!level.done)
					hint();
				break;
			case 'n':
			case 'N':
				/* new */
				generate(time(0));
				drawlevel();
				break;
			case 'r':
			case 'R':
				level = orig;
				drawlevel();
				break;
			case 'c':
			case 'C':
				if(!level.done) {
					clearlevel();
					done();
				}
				break;
			case 8:
			case 'u':
			case 'U':
				if(level.done) {
					level.done = 0;
					drawlevel();
				}
				undo();
				break;
			}
			break;
		}
	}
}