shithub: weiqi

ref: 210c31fdc8bbfe0f008fc0258fdf84c4e9b1de4b
dir: /weiqi.c/

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

enum {
	Boardsize = 13,
	Radius = 15,
	Square = 2 * Radius,
	Border = Square,
	BoardX = Boardsize + (Boardsize - 1) * Square + 2 * Border,
	BoardY = BoardX,

	Phei = 'h',
	Pbai = 'b',
};

static char *decisions[] = {
	"Pass",
	"Undo",
	"Clear",
	"Abandon",
	nil,
};

static Menu menu = {
	decisions,
};

static char piece;
static char board[Boardsize * Boardsize];

static Image *hei;
static Image *bai;
static Image *bg;

static void
resize(void)
{
	int fd;

	fd = open("/dev/wctl", OWRITE);
	if(fd >= 0){
		fprint(fd, "resize -dx %d -dy %d", BoardX, BoardY);
		close(fd);
	}

}

static Point
lies(int i)
{
	int x, y;

	x = i % Boardsize;
	y = i / Boardsize;
	return Pt(Border + 2 * x * Radius, Border + 2 * y * Radius);
}

static int
click(Point m)
{
	int i;
	Point p;
	Rectangle r;

	for(i = 0; i < Boardsize * Boardsize; i++){
		p = lies(i);
		r = Rect(p.x - Radius, p.y - Radius, p.x + Radius, p.y + Radius);
		if(ptinrect(m, r)){
			if(board[i] == 0){
				board[i] = piece;
				piece = piece == Pbai ? Phei : Pbai;
				return 1;
			}
			break;
		}
	}
	return 0;
}

static void
drawscreen(void)
{
	Point p0, p1;
	char c;
	int i;

	draw(screen, screen->r, bg, nil, ZP);
	for(i = 0; i < Boardsize; i++){
		p0 = addpt(screen->r.min, Pt(Border + i * Square, Border));
		p1 = addpt(screen->r.min, Pt(Border + i * Square, BoardX - Border - Boardsize));
		line(screen, p0, p1, Enddisc, Enddisc, 0, hei, ZP);

		p0 = addpt(screen->r.min, Pt(Border, Border + i * Square));
		p1 = addpt(screen->r.min, Pt(BoardY - Border - Boardsize, Border + i * Square));
		line(screen, p0, p1, Enddisc, Enddisc, 0, hei, ZP);
	}
	for(i = 0; i < Boardsize * Boardsize; i++){
		c = board[i];
		if(c == 0)
			continue;

		p0 = addpt(screen->r.min, lies(i));
		fillellipse(screen, p0, Radius, Radius, c == Pbai ? bai : hei, ZP);
		ellipse(screen, p0, Radius, Radius, 0, hei, ZP);
	}
	flushimage(display, 1);
}

/* Modified from Sudoku */
void
eresized(int new)
{
	Point p;

	if(new && getwindow(display, Refnone) < 0)
		sysfatal("resize failed");

	if(hei == nil)
		hei = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, DBlack);
	if(bai == nil)
		bai = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, DWhite);
	if(bg == nil)
		bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xF2B06DFF);

	p = Pt(Dx(screen->r), Dy(screen->r));

	if(!new || !eqpt(p, Pt(BoardX - 8, BoardY - 8)))
		resize();

	drawscreen();
}

void
main()
{
	Event e;
	Mouse m;
	Point p;
	int held = 0;

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

	piece = Phei;

	for(;;){
		switch(event(&e)){
		case Emouse:
			m = e.mouse;
			if(m.buttons & 1){
				if(held)
					break;
				held = 1;
				p = subpt(m.xy, screen->r.min);
				if(click(p))
					drawscreen();
			}else
				held = 0;
			if(m.buttons & 4){
				switch(emenuhit(3, &m, &menu)) {
				case 0:		/* Pass */
					piece = piece == Pbai ? Phei : Pbai;
					break;
				case 1:		/* Undo */
					break;
				case 2:		/* Clear */
					memset(board, 0, Boardsize * Boardsize);
					piece = Phei;
					drawscreen();
					break;
				case 3:		/* Abandon */
					exits(nil);
					break;
				}
			}
			break;
		case Ekeyboard:
			switch(e.kbdc){
			case 127:
			case 'q':
			case 'Q':
				exits(nil);
			}
			break;
		}
	}
}