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;
+ }
+ }
+}