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