💾 Archived View for runjimmyrunrunyoufuckerrun.com › src › games › nurikabe.c captured on 2021-12-17 at 13:26:06.

View Raw

More Information

-=-=-=-=-=-=-

#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.h>

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