#include #include #include #include enum{ SOL = 64, DOT = 32, SEA = 16, NUM = 15, DIM = 9, DIM2 = 81, SQ = 50 }; char *gamefile = "/sys/games/lib/nurikabe"; char *fontname = "/lib/font/bit/pelm/ascii.16.font"; char *cmds[] = {"show solution", "restart", "new", "exit", nil}; char puz[DIM2]; Font *f; int sol; void drawsq(int n) { Image *colour; Rectangle r; char s[2]; colour = puz[n] & (sol ? SOL : SEA) ? display->black : display->white; r.min = addpt(screen->r.min, Pt(Borderwidth, Borderwidth)); r.min = addpt(r.min, mulpt(Pt(n % DIM, n / DIM), SQ)); r.max = addpt(r.min, Pt(SQ - Borderwidth, SQ - Borderwidth)); draw(screen, r, colour, nil, ZP); if(puz[n] & DOT){ colour = sol ? display->white : display->black; r = insetrect(r, (SQ - Borderwidth >> 1) - 4); draw(screen, r, colour, nil, ZP); } else if(puz[n] & NUM){ sprint(s, "%X", puz[n]); r.min.x += SQ - stringwidth(f, s) >> 1; r.min.y += SQ - f->height >> 1; string(screen, r.min, display->black, ZP, f, s); } } void drawsqq(void) { int i; for(i = 0; i < DIM2; i++) drawsq(i); flushimage(display, 1); } void eresized(int new) { int fd; if(new && getwindow(display, Refnone) < 0) sysfatal("can't reattach to window"); if((!new || Dx(screen->r) != DIM * SQ + Borderwidth || Dy(screen->r) != DIM * SQ + Borderwidth) && (fd = open("/dev/wctl", OWRITE)) >= 0){ fprint(fd, "resize -dx %d -dy %d", DIM * SQ + 3 * Borderwidth, DIM * SQ + 3 * Borderwidth); close(fd); } draw(screen, screen->r, display->black, nil, ZP); drawsqq(); } void new(void) { int fd, n; if((fd = open(gamefile, OREAD)) < 0) sysfatal("open: %r"); n = seek(fd, -DIM2 - 1, 2); n = nrand(n) + DIM2 + 1; n -= n % (DIM2 + 1); seek(fd, n, 0); read(fd, puz, DIM2); close(fd); for(n = 0; n < DIM2; n++) switch(puz[n]){ case ' ': puz[n] = 0; break; case '#': puz[n] = SOL; break; default: puz[n] -= '0'; break; } } void main(int, char *argv[]) { Mouse m; Menu menu = {cmds}; int n, b1, b2; if(initdraw(nil, nil, argv[0]) < 0) sysfatal("initdraw: %r"); if((f = openfont(display, fontname)) == nil) sysfatal("can't open font: %r"); einit(Emouse|Ekeyboard); srand(truerand()); new(); eresized(0); for(b1 = b2 = 0;;){ m = emouse(); if(m.buttons & 1) b1 = 1; else if(m.buttons & 2) b2 = 1; else if(m.buttons & 4){ switch(emenuhit(3, &m, &menu)){ case 0: sol ^= 1; break; case 1: for(n = 0; n < DIM2; n++) puz[n] &= ~(SEA | DOT); sol = 0; break; case 2: new(); sol = 0; break; case 3: exits(nil); } strncpy(cmds[0], sol ? "hide" : "show", 4); menu.lasthit = 0; drawsqq(); } else if(b1 | b2){ n = (m.xy.y - screen->r.min.y) / SQ * DIM; n += (m.xy.x - screen->r.min.x) / SQ; if(!sol && n >= 0 && n < DIM2 && !(puz[n] & NUM)){ puz[n] ^= b1 && !(puz[n] & DOT) ? SEA : DOT; drawsq(n); } b1 = b2 = 0; } } }