Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.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;
                }
        }
}