shithub: weiqi

Download patch

ref: 210c31fdc8bbfe0f008fc0258fdf84c4e9b1de4b
author: kws <kws@cirno>
date: Thu Jun 15 18:14:40 EDT 2023

weiqi be born

--- /dev/null
+++ b/mkfile
@@ -1,0 +1,8 @@
+</$objtype/mkfile
+
+TARG=weiqi
+
+OFILES=\
+	weiqi.$O\
+
+</sys/src/cmd/mkone
--- /dev/null
+++ b/weiqi.c
@@ -1,0 +1,191 @@
+#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;
+		}
+	}
+}