ref: 210c31fdc8bbfe0f008fc0258fdf84c4e9b1de4b
dir: /weiqi.c/
#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; } } }