xref: /plan9/sys/src/games/sudoku/sudoku.c (revision d8f3f65ed104b5f1fe09dbf8d8d4b5289e0e4acf)
15fe11e25SDavid du Colombier /* code from mark huckvale: http://www.phon.ucl.ac.uk/home/mark/sudoku/ */
25fe11e25SDavid du Colombier 
35fe11e25SDavid du Colombier #include <u.h>
45fe11e25SDavid du Colombier #include <libc.h>
55fe11e25SDavid du Colombier #include <draw.h>
65fe11e25SDavid du Colombier #include <event.h>
75fe11e25SDavid du Colombier 
85fe11e25SDavid du Colombier #include "sudoku.h"
95fe11e25SDavid du Colombier 
105fe11e25SDavid du Colombier char *imgdir = "/sys/games/lib/sudoku/images";
115fe11e25SDavid du Colombier char *lvldir = "/sys/games/lib/sudoku/boards";	/* level library dir */
125fe11e25SDavid du Colombier 
135fe11e25SDavid du Colombier int selected;	/* which digit do we have selected? */
145fe11e25SDavid du Colombier 
155fe11e25SDavid du Colombier Image *background;	/* DPaleyellow */
165fe11e25SDavid du Colombier Image *backselect;	/* DPalebluegreen */
175fe11e25SDavid du Colombier Image *blink;		/* DDarkyellow */
185fe11e25SDavid du Colombier Image *brdr;		/* 0x55555555 */
195fe11e25SDavid du Colombier Image *fixed;		/* DBlue */
205fe11e25SDavid du Colombier Image *wrong;		/* DRed */
215fe11e25SDavid du Colombier Image *dig[10];		/* digit masks */
225fe11e25SDavid du Colombier 
235fe11e25SDavid du Colombier Dir *dir;
245fe11e25SDavid du Colombier int numlevels;
255fe11e25SDavid du Colombier int curlevel;
265fe11e25SDavid du Colombier 
275fe11e25SDavid du Colombier char *buttons[] =
285fe11e25SDavid du Colombier {
295fe11e25SDavid du Colombier 	"new",
305fe11e25SDavid du Colombier 	"check",
315fe11e25SDavid du Colombier 	"solve",
325fe11e25SDavid du Colombier 	"clear",
335fe11e25SDavid du Colombier 	"save",
345fe11e25SDavid du Colombier 	"load",
355fe11e25SDavid du Colombier 	"print",
365fe11e25SDavid du Colombier 	"offline",
375fe11e25SDavid du Colombier 	"exit",
385fe11e25SDavid du Colombier 	0
395fe11e25SDavid du Colombier };
405fe11e25SDavid du Colombier 
415fe11e25SDavid du Colombier Menu menu =
425fe11e25SDavid du Colombier {
435fe11e25SDavid du Colombier 	buttons
445fe11e25SDavid du Colombier };
455fe11e25SDavid du Colombier 
465fe11e25SDavid du Colombier Menu lmenu =
475fe11e25SDavid du Colombier {
485fe11e25SDavid du Colombier 	nil,
495fe11e25SDavid du Colombier 	genlevels,
505fe11e25SDavid du Colombier 	0,
515fe11e25SDavid du Colombier };
525fe11e25SDavid du Colombier 
535fe11e25SDavid du Colombier int
readlevels(char * leveldir)545fe11e25SDavid du Colombier readlevels(char *leveldir)
555fe11e25SDavid du Colombier {
565fe11e25SDavid du Colombier 	int fd, n;
575fe11e25SDavid du Colombier 
585fe11e25SDavid du Colombier 	if((fd = open(leveldir, OREAD)) < 0)
595fe11e25SDavid du Colombier 		return -1;
605fe11e25SDavid du Colombier 
615fe11e25SDavid du Colombier 	n = dirreadall(fd, &dir);
625fe11e25SDavid du Colombier 	close(fd);
635fe11e25SDavid du Colombier 
645fe11e25SDavid du Colombier 	return n;
655fe11e25SDavid du Colombier }
665fe11e25SDavid du Colombier 
675fe11e25SDavid du Colombier char *
genlevels(int i)685fe11e25SDavid du Colombier genlevels(int i)
695fe11e25SDavid du Colombier {
705fe11e25SDavid du Colombier 	if(numlevels == 0)
715fe11e25SDavid du Colombier 		numlevels = readlevels(lvldir);
725fe11e25SDavid du Colombier 
735fe11e25SDavid du Colombier 	if(numlevels > 0 && i < numlevels)
745fe11e25SDavid du Colombier 		return (dir+i)->name;
755fe11e25SDavid du Colombier 
765fe11e25SDavid du Colombier 	return nil;
775fe11e25SDavid du Colombier }
785fe11e25SDavid du Colombier 
795fe11e25SDavid du Colombier void
convert(Cell * brd,int * board)805fe11e25SDavid du Colombier convert(Cell *brd, int *board)
815fe11e25SDavid du Colombier {
825fe11e25SDavid du Colombier 	int i;
835fe11e25SDavid du Colombier 
845fe11e25SDavid du Colombier 	for(i = 0; i < Psize; i++) {
855fe11e25SDavid du Colombier 		brd[i].digit = board[i] & Digit;
865fe11e25SDavid du Colombier 		if(brd[i].digit < 0 || brd[i].digit > 9)
875fe11e25SDavid du Colombier 			brd[i].digit = -1;
885fe11e25SDavid du Colombier 		brd[i].solve = (board[i] & Solve) >> 4;
895fe11e25SDavid du Colombier 		brd[i].locked = board[i] & MLock;
905fe11e25SDavid du Colombier 	}
915fe11e25SDavid du Colombier 	memcpy(obrd, brd, Psize * sizeof(Cell));
925fe11e25SDavid du Colombier }
935fe11e25SDavid du Colombier 
945fe11e25SDavid du Colombier Image *
eallocimage(Rectangle r,int repl,uint color)955fe11e25SDavid du Colombier eallocimage(Rectangle r, int repl, uint color)
965fe11e25SDavid du Colombier {
975fe11e25SDavid du Colombier 	Image *tmp;
985fe11e25SDavid du Colombier 
995fe11e25SDavid du Colombier 	tmp = allocimage(display, r, screen->chan, repl, color);
1005fe11e25SDavid du Colombier 	if(tmp == nil)
1015fe11e25SDavid du Colombier 		sysfatal("cannot allocate buffer image: %r");
1025fe11e25SDavid du Colombier 
1035fe11e25SDavid du Colombier 	return tmp;
1045fe11e25SDavid du Colombier }
1055fe11e25SDavid du Colombier 
1065fe11e25SDavid du Colombier Image *
eloadfile(char * path)1075fe11e25SDavid du Colombier eloadfile(char *path)
1085fe11e25SDavid du Colombier {
1095fe11e25SDavid du Colombier 	Image *img;
1105fe11e25SDavid du Colombier 	int fd;
1115fe11e25SDavid du Colombier 
1125fe11e25SDavid du Colombier 	fd = open(path, OREAD);
1135fe11e25SDavid du Colombier 	if(fd < 0) {
1145fe11e25SDavid du Colombier 		fprint(2, "cannot open image file %s: %r\n", path);
1155fe11e25SDavid du Colombier 		exits("image");
1165fe11e25SDavid du Colombier 	}
1175fe11e25SDavid du Colombier 	img = readimage(display, fd, 0);
1185fe11e25SDavid du Colombier 	if(img == nil)
1195fe11e25SDavid du Colombier 		sysfatal("cannot load image: %r");
1205fe11e25SDavid du Colombier 	close(fd);
1215fe11e25SDavid du Colombier 
1225fe11e25SDavid du Colombier 	return img;
1235fe11e25SDavid du Colombier }
1245fe11e25SDavid du Colombier 
1255fe11e25SDavid du Colombier 
1265fe11e25SDavid du Colombier void
clearboard(Cell * board)1275fe11e25SDavid du Colombier clearboard(Cell *board)
1285fe11e25SDavid du Colombier {
1295fe11e25SDavid du Colombier 	int i;
1305fe11e25SDavid du Colombier 
1315fe11e25SDavid du Colombier 	for(i = 0; i < Psize; i++) {
1325fe11e25SDavid du Colombier 		board[i].digit = -1;
1335fe11e25SDavid du Colombier 		board[i].solve = 0;
1345fe11e25SDavid du Colombier 		board[i].locked = 0;
1355fe11e25SDavid du Colombier 	}
1365fe11e25SDavid du Colombier }
1375fe11e25SDavid du Colombier 
1385fe11e25SDavid du Colombier void
solveboard(Cell * board)1395fe11e25SDavid du Colombier solveboard(Cell *board)
1405fe11e25SDavid du Colombier {
1415fe11e25SDavid du Colombier 	int i;
1425fe11e25SDavid du Colombier 
1435fe11e25SDavid du Colombier 	for(i = 0; i < Psize; i++) {
1445fe11e25SDavid du Colombier 		board[i].digit = board[i].solve;
1455fe11e25SDavid du Colombier 	}
1465fe11e25SDavid du Colombier }
1475fe11e25SDavid du Colombier 
1485fe11e25SDavid du Colombier 
1495fe11e25SDavid du Colombier int
checkpossible(Cell * board,int x,int y,int num)1505fe11e25SDavid du Colombier checkpossible(Cell *board, int x, int y, int num)
1515fe11e25SDavid du Colombier {
1525fe11e25SDavid du Colombier 	int i, j;
1535fe11e25SDavid du Colombier 
1545fe11e25SDavid du Colombier 	for(i = 0; i < Brdsize; i++) {
1555fe11e25SDavid du Colombier 		if(board[i*Brdsize + y].digit == num && i != x)
1565fe11e25SDavid du Colombier 			return 0;
1575fe11e25SDavid du Colombier 		if(board[x*Brdsize + i].digit == num && i != y)
1585fe11e25SDavid du Colombier 			return 0;
1595fe11e25SDavid du Colombier 	}
1605fe11e25SDavid du Colombier 
1615fe11e25SDavid du Colombier 	for(i = x - (x%3); i < x - (x%3) + 3; i++)
1625fe11e25SDavid du Colombier 		for(j = y - (y%3); j < y - (y%3) + 3; j++)
1635fe11e25SDavid du Colombier 			if((i != x && j != y) && board[i*Brdsize + j].digit == num)
1645fe11e25SDavid du Colombier 				return 0;
1655fe11e25SDavid du Colombier 
1665fe11e25SDavid du Colombier 	return 1;
1675fe11e25SDavid du Colombier }
1685fe11e25SDavid du Colombier 
1695fe11e25SDavid du Colombier void
resize(void)1705fe11e25SDavid du Colombier resize(void)
1715fe11e25SDavid du Colombier {
1725fe11e25SDavid du Colombier 	int fd;
1735fe11e25SDavid du Colombier 
1745fe11e25SDavid du Colombier 	fd = open("/dev/wctl", OWRITE);
1755fe11e25SDavid du Colombier 	if(fd >= 0){
1765fe11e25SDavid du Colombier 		fprint(fd, "resize -dx %d -dy %d", Maxx, Maxy);
1775fe11e25SDavid du Colombier 		close(fd);
1785fe11e25SDavid du Colombier 	}
1795fe11e25SDavid du Colombier 
1805fe11e25SDavid du Colombier }
1815fe11e25SDavid du Colombier 
1825fe11e25SDavid du Colombier void
drawcell(int x,int y,int num,Image * col)1835fe11e25SDavid du Colombier drawcell(int x, int y, int num, Image *col)
1845fe11e25SDavid du Colombier {
1855fe11e25SDavid du Colombier 	Rectangle r = Rect(x*Square, y*Square, (x+1)*Square, (y+1)*Square);
1865fe11e25SDavid du Colombier 
1875fe11e25SDavid du Colombier 	if(num < 0 || num > 9)
1885fe11e25SDavid du Colombier 		return;
1895fe11e25SDavid du Colombier 
1905fe11e25SDavid du Colombier 	r = insetrect(r, Border);
1915fe11e25SDavid du Colombier 	r = rectaddpt(r, Pt(0, Square));
1925fe11e25SDavid du Colombier 	r.max = addpt(r.max, Pt(2, 2));
1935fe11e25SDavid du Colombier 
1945fe11e25SDavid du Colombier 	draw(screen, rectaddpt(r, screen->r.min), col, dig[num], ZP);
1955fe11e25SDavid du Colombier }
1965fe11e25SDavid du Colombier 
1975fe11e25SDavid du Colombier void
drawboard(void)1985fe11e25SDavid du Colombier drawboard(void)
1995fe11e25SDavid du Colombier {
2005fe11e25SDavid du Colombier 	int i;
2015fe11e25SDavid du Colombier 
2025fe11e25SDavid du Colombier 	for(i = 0; i < Psize; i++) {
2035fe11e25SDavid du Colombier 		drawcell(i / Brdsize, i % Brdsize, brd[i].digit, brd[i].locked ? fixed : display->black);
2045fe11e25SDavid du Colombier 	}
2055fe11e25SDavid du Colombier }
2065fe11e25SDavid du Colombier 
2075fe11e25SDavid du Colombier void
drawchecked(Cell * brd)2085fe11e25SDavid du Colombier drawchecked(Cell *brd)
2095fe11e25SDavid du Colombier {
2105fe11e25SDavid du Colombier 	int i;
2115fe11e25SDavid du Colombier 
2125fe11e25SDavid du Colombier 	for(i = 0; i < Psize; i++) {
2135fe11e25SDavid du Colombier 		if(brd[i].locked)
2145fe11e25SDavid du Colombier 			drawcell(i / Brdsize, i % Brdsize, brd[i].digit, fixed);
2155fe11e25SDavid du Colombier 		else
2165fe11e25SDavid du Colombier 			drawcell(i / Brdsize, i % Brdsize, brd[i].digit,
2175fe11e25SDavid du Colombier 					checkpossible(brd, i / Brdsize, i % Brdsize, brd[i].digit) ? display->black : wrong);
2185fe11e25SDavid du Colombier 	}
2195fe11e25SDavid du Colombier }
2205fe11e25SDavid du Colombier 
2215fe11e25SDavid du Colombier void
drawscreen(void)2225fe11e25SDavid du Colombier drawscreen(void)
2235fe11e25SDavid du Colombier {
2245fe11e25SDavid du Colombier 	Point l1, l2;
2255fe11e25SDavid du Colombier 	int i;
2265fe11e25SDavid du Colombier 
2275fe11e25SDavid du Colombier 	draw(screen, screen->r, brdr, nil, ZP);
2285fe11e25SDavid du Colombier 	draw(screen, insetrect(screen->r, Border), background, nil, ZP);
2295fe11e25SDavid du Colombier 	for(i = 0; i < Brdsize; i++) {
2305fe11e25SDavid du Colombier 		l1 = addpt(screen->r.min, Pt(i*Square, Square));
2315fe11e25SDavid du Colombier 		l2 = addpt(screen->r.min, Pt(i*Square, Maxy));
2325fe11e25SDavid du Colombier 		line(screen, l1, l2, Endsquare, Endsquare, (i%3) == 0 ? Thickline : Line, brdr, ZP);
2335fe11e25SDavid du Colombier 		l1 = addpt(screen->r.min, Pt(0, (i+1)*Square));
2345fe11e25SDavid du Colombier 		l2 = addpt(screen->r.min, Pt(Maxx, (i+1)*Square));
2355fe11e25SDavid du Colombier 		line(screen, l1, l2, Endsquare, Endsquare, (i%3) == 0 ? Thickline : Line, brdr, ZP);
2365fe11e25SDavid du Colombier 	}
2375fe11e25SDavid du Colombier 	for(i = 1; i < 10; i++) {
2385fe11e25SDavid du Colombier 		drawbar(i, (selected == i) ? 1 : 0);
2395fe11e25SDavid du Colombier 	}
2405fe11e25SDavid du Colombier 	drawboard();
2415fe11e25SDavid du Colombier 	flushimage(display, 1);
2425fe11e25SDavid du Colombier }
2435fe11e25SDavid du Colombier 
2445fe11e25SDavid du Colombier 
2455fe11e25SDavid du Colombier void
drawbar(int digit,int selected)2465fe11e25SDavid du Colombier drawbar(int digit, int selected)
2475fe11e25SDavid du Colombier {
2485fe11e25SDavid du Colombier 	Rectangle r = Rect((digit - 1)*Square, 0, digit*Square, Square);
2495fe11e25SDavid du Colombier 
2505fe11e25SDavid du Colombier 	if(digit < 1 || digit > 9)
2515fe11e25SDavid du Colombier 		return;
2525fe11e25SDavid du Colombier 
2535fe11e25SDavid du Colombier 	r = insetrect(r, Border);
2545fe11e25SDavid du Colombier 	r.max = addpt(r.max, Pt(2, 2));
2555fe11e25SDavid du Colombier 	draw(screen, rectaddpt(r, screen->r.min), selected ? backselect : background, nil, ZP);
2565fe11e25SDavid du Colombier 	draw(screen, rectaddpt(r, screen->r.min), display->black, dig[digit-1], ZP);
2575fe11e25SDavid du Colombier }
2585fe11e25SDavid du Colombier 
2595fe11e25SDavid du Colombier void
eresized(int new)2605fe11e25SDavid du Colombier eresized(int new)
2615fe11e25SDavid du Colombier {
2625fe11e25SDavid du Colombier 	Point p;
2635fe11e25SDavid du Colombier 	char path[256];
2645fe11e25SDavid du Colombier 	int i;
2655fe11e25SDavid du Colombier 
2665fe11e25SDavid du Colombier 	if(new && getwindow(display, Refnone) < 0)
2675fe11e25SDavid du Colombier 		sysfatal("can't reattach to window");
2685fe11e25SDavid du Colombier 
2695fe11e25SDavid du Colombier 	if(background == nil)
2705fe11e25SDavid du Colombier 		background = eallocimage(Rect(0, 0, 1, 1), 1, DPaleyellow);
2715fe11e25SDavid du Colombier 	if(backselect == nil)
2725fe11e25SDavid du Colombier 		backselect = eallocimage(Rect(0, 0, 1, 1), 1, DPalebluegreen);
2735fe11e25SDavid du Colombier 	if(blink == nil)
2745fe11e25SDavid du Colombier 		blink = eallocimage(Rect(0, 0, 1, 1), 1, DDarkyellow);
2755fe11e25SDavid du Colombier 	if(brdr == nil)
2765fe11e25SDavid du Colombier 		brdr = eallocimage(Rect(0, 0, 1, 1), 1, 0x55555555);
2775fe11e25SDavid du Colombier 	if(fixed == nil)
2785fe11e25SDavid du Colombier 		fixed = eallocimage(Rect(0, 0, 1, 1), 1, DBlue);
2795fe11e25SDavid du Colombier 	if(wrong == nil)
2805fe11e25SDavid du Colombier 		wrong = eallocimage(Rect(0, 0, 1, 1), 1, DRed);
2815fe11e25SDavid du Colombier 	if(dig[0] == nil) {
2825fe11e25SDavid du Colombier 		for(i = 0; i < 9; i++) {
2835fe11e25SDavid du Colombier 			snprint(path, 256, "%s/%d.bit", imgdir, i+1);
2845fe11e25SDavid du Colombier 			dig[i] = eloadfile(path);
2855fe11e25SDavid du Colombier 		}
2865fe11e25SDavid du Colombier 	}
2875fe11e25SDavid du Colombier 
2885fe11e25SDavid du Colombier 	p = Pt(Dx(screen->r), Dy(screen->r));
289*d8f3f65eSDavid du Colombier 	if(!new || !eqpt(p, Pt(Maxx - 8, Maxy - 8)))
2905fe11e25SDavid du Colombier 		resize();
291*d8f3f65eSDavid du Colombier 
2925fe11e25SDavid du Colombier 	drawscreen();
2935fe11e25SDavid du Colombier }
2945fe11e25SDavid du Colombier 
2955fe11e25SDavid du Colombier void
main(int argc,char * argv[])2965fe11e25SDavid du Colombier main(int argc, char *argv[])
2975fe11e25SDavid du Colombier {
2985fe11e25SDavid du Colombier 	Mouse m;
2995fe11e25SDavid du Colombier 	Event e;
3005fe11e25SDavid du Colombier 	Point p;
3015fe11e25SDavid du Colombier 	int last1 = 0;	/* was the button clicked last time? */
3025fe11e25SDavid du Colombier 
3035fe11e25SDavid du Colombier 	USED(argc, argv);
3045fe11e25SDavid du Colombier 
3055fe11e25SDavid du Colombier 	if(initdraw(nil, nil, "sudoku") < 0)
3065fe11e25SDavid du Colombier 		sysfatal("initdraw failed: %r");
3075fe11e25SDavid du Colombier 
3085fe11e25SDavid du Colombier 	einit(Emouse|Ekeyboard);
3095fe11e25SDavid du Colombier 
3105fe11e25SDavid du Colombier 
3115fe11e25SDavid du Colombier 	clearboard(brd);
3125fe11e25SDavid du Colombier 	eresized(0);
3135fe11e25SDavid du Colombier 
3145fe11e25SDavid du Colombier 	srand(time(0)*getpid());
3155fe11e25SDavid du Colombier 	makep();
3165fe11e25SDavid du Colombier 	convert(brd, board);
3175fe11e25SDavid du Colombier 
3185fe11e25SDavid du Colombier 	drawscreen();
3195fe11e25SDavid du Colombier 	for(;;) {
3205fe11e25SDavid du Colombier 		switch(event(&e)) {
3215fe11e25SDavid du Colombier 		case Emouse:
3225fe11e25SDavid du Colombier 			m = e.mouse;
3235fe11e25SDavid du Colombier 			if(m.buttons&1) {
3245fe11e25SDavid du Colombier 				if(last1 == 0) {
3255fe11e25SDavid du Colombier 					last1 = 1;
3265fe11e25SDavid du Colombier 					p = subpt(m.xy, screen->r.min);
3275fe11e25SDavid du Colombier 					if(ptinrect(p, Rect(0, 0, Maxx, Square+Border))) {
3285fe11e25SDavid du Colombier 						if(p.x/Square == selected - 1) {
3295fe11e25SDavid du Colombier 							drawbar(selected, 0);
3305fe11e25SDavid du Colombier 							selected = 0;
3315fe11e25SDavid du Colombier 						} else {
3325fe11e25SDavid du Colombier 							selected = p.x/Square + 1;
3335fe11e25SDavid du Colombier 						}
3345fe11e25SDavid du Colombier 					} else {
3355fe11e25SDavid du Colombier 						Point lp = divpt(p, Square);
3365fe11e25SDavid du Colombier 						lp.y--;
3375fe11e25SDavid du Colombier 
3385fe11e25SDavid du Colombier 						if(brd[lp.x * Brdsize + lp.y].locked)
3395fe11e25SDavid du Colombier 							break;
3405fe11e25SDavid du Colombier 
3415fe11e25SDavid du Colombier 						if(selected) {
3425fe11e25SDavid du Colombier 							brd[lp.x * Brdsize + lp.y].digit = selected - 1;
3435fe11e25SDavid du Colombier 						} else {
3445fe11e25SDavid du Colombier 							brd[lp.x * Brdsize + lp.y].digit = -1;
3455fe11e25SDavid du Colombier 						}
3465fe11e25SDavid du Colombier 					}
3475fe11e25SDavid du Colombier 					drawscreen();
3485fe11e25SDavid du Colombier 				}
3495fe11e25SDavid du Colombier 			} else {
3505fe11e25SDavid du Colombier 				last1 = 0;
3515fe11e25SDavid du Colombier 			}
3525fe11e25SDavid du Colombier 
3535fe11e25SDavid du Colombier 			if(m.buttons&2) {
3545fe11e25SDavid du Colombier 				char *str;
3555fe11e25SDavid du Colombier 				int l;
3565fe11e25SDavid du Colombier 				/* levels start from 1 */
3575fe11e25SDavid du Colombier 				lmenu.lasthit = curlevel;
3585fe11e25SDavid du Colombier 				l = emenuhit(2, &m, &lmenu);
3595fe11e25SDavid du Colombier 				if(l >= 0){
3605fe11e25SDavid du Colombier 					curlevel = l;
3615fe11e25SDavid du Colombier 					str = smprint("%s/%s", lvldir, (dir+curlevel)->name);
3625fe11e25SDavid du Colombier 					if(loadlevel(str, brd) < 0)
3635fe11e25SDavid du Colombier 						clearboard(brd);
3645fe11e25SDavid du Colombier 					memcpy(obrd, brd, Psize * sizeof(Cell));
3655fe11e25SDavid du Colombier 					free(str);
3665fe11e25SDavid du Colombier 				}
3675fe11e25SDavid du Colombier 				drawscreen();
3685fe11e25SDavid du Colombier 			}
3695fe11e25SDavid du Colombier 			if(m.buttons&4) {
3705fe11e25SDavid du Colombier 				switch(emenuhit(3, &m, &menu)) {
3715fe11e25SDavid du Colombier 				case 0: 	/* new */
3725fe11e25SDavid du Colombier 					makep();
3735fe11e25SDavid du Colombier 					convert(brd, board);
3745fe11e25SDavid du Colombier 					drawscreen();
3755fe11e25SDavid du Colombier 					break;
3765fe11e25SDavid du Colombier 				case 1:		/* solve */
3775fe11e25SDavid du Colombier 					drawchecked(brd);
3785fe11e25SDavid du Colombier 					break;
3795fe11e25SDavid du Colombier 				case 2:		/* solve */
3805fe11e25SDavid du Colombier 					solveboard(brd);
3815fe11e25SDavid du Colombier 					drawscreen();
3825fe11e25SDavid du Colombier 					break;
3835fe11e25SDavid du Colombier 				case 3:		/* clear */
3845fe11e25SDavid du Colombier 					memcpy(brd, obrd, Psize * sizeof(Cell));
3855fe11e25SDavid du Colombier 					drawscreen();
3865fe11e25SDavid du Colombier 					break;
3875fe11e25SDavid du Colombier 				case 4:		/* save */
3885fe11e25SDavid du Colombier 					savegame(brd);
3895fe11e25SDavid du Colombier 					drawscreen();
3905fe11e25SDavid du Colombier 					break;
3915fe11e25SDavid du Colombier 				case 5:		/* load */
3925fe11e25SDavid du Colombier 					if(loadgame(brd) < 0) {
3935fe11e25SDavid du Colombier 						clearboard(brd);
3945fe11e25SDavid du Colombier 					}
3955fe11e25SDavid du Colombier 					memcpy(obrd, brd, Psize * sizeof(Cell));
3965fe11e25SDavid du Colombier 					drawscreen();
3975fe11e25SDavid du Colombier 					break;
3985fe11e25SDavid du Colombier 				case 6:		/* print */
3995fe11e25SDavid du Colombier 					printboard(brd);
4005fe11e25SDavid du Colombier 					break;
4015fe11e25SDavid du Colombier 				case 7:		/* offline */
4025fe11e25SDavid du Colombier 					fprettyprintbrd(brd);
4035fe11e25SDavid du Colombier 					break;
4045fe11e25SDavid du Colombier 				case 8:		/* exit */
4055fe11e25SDavid du Colombier 					exits(nil);
4065fe11e25SDavid du Colombier 				}
4075fe11e25SDavid du Colombier 			}
4085fe11e25SDavid du Colombier 			break;
4095fe11e25SDavid du Colombier 
4105fe11e25SDavid du Colombier 		case Ekeyboard:
4115fe11e25SDavid du Colombier 			switch(e.kbdc) {
4125fe11e25SDavid du Colombier 			case 127:
4135fe11e25SDavid du Colombier 			case 'q':
4145fe11e25SDavid du Colombier 			case 'Q':
4155fe11e25SDavid du Colombier 				exits(nil);
4165fe11e25SDavid du Colombier 			default:
4175fe11e25SDavid du Colombier 				break;
4185fe11e25SDavid du Colombier 			}
4195fe11e25SDavid du Colombier 			break;
4205fe11e25SDavid du Colombier 		}
4215fe11e25SDavid du Colombier 	}
4225fe11e25SDavid du Colombier }
423