shithub: cflood

Download patch

ref: eeeee42a3e9eafb35fe71f7f8bd553759065aa85
parent: 3eb5bf930b5cce1f8c6eb7851ebaa158ceaadfc8
author: Sigrid Solveig Haflínudóttir <248148+ftrvxmtrx@users.noreply.github.com>
date: Sat Mar 23 06:57:17 EDT 2013

move and add -b option to usage output

diff: cannot open a/games//null: file does not exist: 'a/games//null'
--- /dev/null
+++ b/cflood.c
@@ -1,0 +1,330 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <event.h>
+
+enum{
+	/* sid */
+	Ssmall,
+	Snormal,
+	Slarge,
+	Scustom,
+
+	/* state */
+	Tgame,
+	Twin,
+	Tfail,
+
+	/* cell flags & masks */
+	Flood = 1<<7,
+	Redraw = 1<<6,
+	ColorMask = 0x0f,
+
+	NumColors = 6,
+	ButtonSize = 32
+};
+
+static int sizes[] = {
+	14, 21, 28, 1
+};
+
+static int turns[] = {
+	25, 35, 50, 1
+};
+
+static const ulong srccolors[NumColors] = {
+	0x6060a8ff,
+	0xf6f61dff,
+	0x46b0e0ff,
+	0x7ea020ff,
+	0xf070a0ff,
+	0xdc4a20ff
+};
+
+static char *mstr[] = {
+	"14x14 / 25",
+	"25x25 / 35",
+	"28x28 / 50",
+	"exit",
+	nil, /* the extra for "custom" */
+	nil
+};
+
+static int size;
+static int sid;
+static int state;
+static int clickwait;
+static int turnsleft;
+static uchar *cells;
+static Image *colors[NumColors];
+static Rectangle buttons[NumColors];
+static Image *colora, *colorb;
+
+static void
+floodneighbours(uchar color, int x, int y);
+
+static void
+redraw(Image *screen, int full)
+{
+	static Point p, sp, strsize;
+	int i, x, y, w, h, csize, left;
+	uchar *c;
+	Rectangle r;
+	char s[64];
+	Font *f;
+
+	sp.x = sp.y = 0;
+
+	/* clear the old caption */
+	draw(screen, Rect(p.x, p.y, p.x+strsize.x, p.y+strsize.y), colora, nil, ZP);
+
+	if(state == Tgame)
+		sprint(s, "%d", turnsleft);
+	else if(state == Twin)
+		sprint(s, "You won using %d turns (of %d)", turns[sid]-turnsleft, turns[sid]);
+	else if(state == Tfail)
+		sprint(s, "You failed");
+
+	f = display->defaultfont;
+	strsize = stringsize(f, s);
+
+	w = Dx(screen->r);
+	h = Dy(screen->r) - ButtonSize - 4 - strsize.y;
+	csize = (w < h ? w : h) / size;
+	w = size*csize;
+	left = screen->r.min.x + (Dx(screen->r) - w)/2;
+
+	/* buttons top */
+	y = screen->r.min.y + h + 2 + strsize.y;
+
+	if(full){
+		/* background */
+		draw(screen, screen->r, colora, nil, ZP);
+
+		/* buttons */
+		x = left + (w - NumColors*ButtonSize)/2;
+		for(i = 0; i < NumColors; i++, x += ButtonSize){
+			buttons[i] = Rect(x, y, x+ButtonSize, y+ButtonSize);
+			draw(screen, buttons[i], colors[i], nil, ZP);
+		}
+	}
+
+	/* caption */
+	p.x = left + w/2 - strsize.x/2;
+	p.y = y - strsize.y;
+	string(screen, p, colorb, sp, f, s);
+
+	/* cells */
+	c = cells;
+	for(x = 0; x < size; x++){
+		for(y = 0; y < size; y++, c++){
+			if((*c & Redraw) != 0 || full){
+				*c &= ~Redraw;
+				r.min.x = left + x*csize;
+				r.min.y = screen->r.min.y + 2 + y*csize;
+				r.max.x = r.min.x + csize;
+				r.max.y = r.min.y + csize;
+				draw(screen, r, colors[*c & ColorMask], nil, ZP);
+			}
+		}
+	}
+
+	flushimage(display, 1);
+}
+
+static void
+floodrecurse(uchar color, int x, int y)
+{
+	uchar *c;
+	c = &cells[x + y*size];
+	if((*c & Flood) == 0 && (*c & ColorMask) == color){
+		floodneighbours(color, x, y);
+	}
+}
+
+static void
+floodneighbours(uchar color, int x, int y)
+{
+	cells[x + y*size] = color|Flood|Redraw;
+
+	if(x > 0)
+		floodrecurse(color, x-1, y);
+	if(x < size-1)
+		floodrecurse(color, x+1, y);
+	if(y > 0)
+		floodrecurse(color, x, y-1);
+	if(y < size-1)
+		floodrecurse(color, x, y+1);
+}
+
+static int
+reflood(uchar color)
+{
+	int n, x, y;
+
+	color &= ColorMask;
+
+	n = 0;
+	for(x = 0; x < size; x++){
+		for(y = 0; y < size; y++){
+			if(cells[x + y*size] & Flood){
+				floodneighbours(color, x, y);
+				n++;
+			}
+		}
+	}
+	return n;
+}
+
+static void
+flood(uchar color)
+{
+	int n;
+
+	if((cells[0] & Flood) != 0 && (cells[0] & ColorMask) == color)
+		return;
+
+	if(!turnsleft)
+		return;
+
+	turnsleft--;
+	n = reflood(color);
+
+	if(n == size*size){
+		state = Twin;
+		clickwait = 1;
+	}else if(!turnsleft){
+		state = Tfail;
+		clickwait = 1;
+	}
+
+	redraw(screen, 0);
+}
+
+static void
+newgame(int sid)
+{
+	uchar *c;
+	int i, maxsize;
+
+	state = Tgame;
+	size = sizes[sid];
+	turnsleft = turns[sid];
+	clickwait = 0;
+
+	if(cells == nil){
+		maxsize = (size > sizes[Slarge]) ? size : sizes[Slarge];
+		cells = malloc(maxsize*maxsize);
+	}
+
+	/* randomize */
+	c = cells;
+	for(i = 0; i < size*size; i++){
+		*c++ = nrand(NumColors);
+	}
+
+	cells[0] |= Flood|Redraw;
+	reflood(cells[0]);
+	redraw(screen, 1);
+}
+
+void
+eresized(int new)
+{
+	if(new && getwindow(display, Refnone) < 0)
+		sysfatal("can't reattach to window: %r");
+	redraw(screen, 1);
+}
+
+static void
+usage(void)
+{
+	fprint(2, "usage: cflood [-b] [-s size] [-t turns]\n");
+	exits("usage");
+}
+
+void
+main(int argc, char** argv)
+{
+	int key, p, i, oldbuttons, sidmax, inv;
+	Event e;
+	Mouse m;
+	Menu menu;
+	Rectangle r;
+
+	sid = Ssmall;
+	inv = 0;
+	ARGBEGIN{
+	case 'b':
+		inv = 1;
+		break;
+	case 's':
+		sid = Scustom;
+		sizes[sid] = atoi(ARGF());
+		if(sizes[sid] < 1)
+			usage();
+		break;
+	case 't':
+		sid = Scustom;
+		turns[sid] = atoi(ARGF());
+		if(turns[sid] < 1)
+			usage();
+		break;
+	default:
+		usage();
+	}ARGEND
+
+	if(initdraw(0, 0, "cflood") < 0)
+		sysfatal("initdraw failed");
+
+	r = Rect(0, 0, 1, 1);
+	for(i = 0; i < NumColors; i++)
+		colors[i] = allocimage(display, r, CMAP8, 1, srccolors[i]);
+
+	colora = inv ? display->black : display->white;
+	colorb = inv ? display->white : display->black;
+
+	einit(Emouse);
+	menu.item = mstr;
+	menu.lasthit = 0;
+	srand(time(0));
+
+	sidmax = (sid > Slarge) ? sid : Slarge;
+	if(sid == Scustom){
+		/* move "exit" and add "custom" size/turns */
+		sidmax = sid;
+		mstr[Scustom+1] = mstr[Scustom];
+		mstr[Scustom] = smprint("%dx%d / %d", sizes[sid], sizes[sid], turns[sid]);
+	}
+
+	newgame(sid);
+
+	for(oldbuttons = 0;;){
+		key = event(&e);
+		m = e.mouse;
+
+		if(key != Emouse)
+			continue;
+
+		if(m.buttons & 4){
+			p = emenuhit(3, &m, &menu);
+			if(p >= Ssmall && p <= sidmax)
+				newgame(sid = p);
+			else if(p > 0)
+				break;
+		}else if(clickwait && !oldbuttons && m.buttons){
+			newgame(sid);
+		}else if(m.buttons & 1){
+			for(i = 0; i < NumColors; i++){
+				if(ptinrect(m.xy, buttons[i])){
+					flood(i);
+					break;
+				}
+			}
+		}
+
+		oldbuttons = m.buttons;
+	}
+
+	exits(nil);
+}
--- /dev/null
+++ b/cflood.man
@@ -1,0 +1,41 @@
+.TH CFLOOD 1
+.SH NAME
+cflood \- a timewaster
+.SH SYNOPSIS
+.B cflood
+[
+.I -b
+]
+[
+.I -s size
+]
+[
+.I -t turns
+]
+.SH DESCRIPTION
+.I cflood
+is a game in which player must fill an area with one color in a limited number of turns.
+.PP
+The
+.B -b
+option reverses the color scheme for text and background.
+.PP
+The
+.B -s
+option sets the size of the area to
+.IR size
+x
+.IR size .
+.PP
+The
+.B -t
+option sets the number of
+.IR turns .
+.EE
+.PP
+There are three predefined area sizes in the game menu (invoked by button 3).
+.EE
+.SH SOURCE
+http://bitbucket.org/ftrvxmtrx/p9
+.SH BUGS
+Of course.
--- a/games/cflood.c
+++ /dev/null
@@ -1,330 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <event.h>
-
-enum{
-	/* sid */
-	Ssmall,
-	Snormal,
-	Slarge,
-	Scustom,
-
-	/* state */
-	Tgame,
-	Twin,
-	Tfail,
-
-	/* cell flags & masks */
-	Flood = 1<<7,
-	Redraw = 1<<6,
-	ColorMask = 0x0f,
-
-	NumColors = 6,
-	ButtonSize = 32
-};
-
-static int sizes[] = {
-	14, 21, 28, 1
-};
-
-static int turns[] = {
-	25, 35, 50, 1
-};
-
-static const ulong srccolors[NumColors] = {
-	0x6060a8ff,
-	0xf6f61dff,
-	0x46b0e0ff,
-	0x7ea020ff,
-	0xf070a0ff,
-	0xdc4a20ff
-};
-
-static char *mstr[] = {
-	"14x14 / 25",
-	"25x25 / 35",
-	"28x28 / 50",
-	"exit",
-	nil, /* the extra for "custom" */
-	nil
-};
-
-static int size;
-static int sid;
-static int state;
-static int clickwait;
-static int turnsleft;
-static uchar *cells;
-static Image *colors[NumColors];
-static Rectangle buttons[NumColors];
-static Image *colora, *colorb;
-
-static void
-floodneighbours(uchar color, int x, int y);
-
-static void
-redraw(Image *screen, int full)
-{
-	static Point p, sp, strsize;
-	int i, x, y, w, h, csize, left;
-	uchar *c;
-	Rectangle r;
-	char s[64];
-	Font *f;
-
-	sp.x = sp.y = 0;
-
-	/* clear the old caption */
-	draw(screen, Rect(p.x, p.y, p.x+strsize.x, p.y+strsize.y), colora, nil, ZP);
-
-	if(state == Tgame)
-		sprint(s, "%d", turnsleft);
-	else if(state == Twin)
-		sprint(s, "You won using %d turns (of %d)", turns[sid]-turnsleft, turns[sid]);
-	else if(state == Tfail)
-		sprint(s, "You failed");
-
-	f = display->defaultfont;
-	strsize = stringsize(f, s);
-
-	w = Dx(screen->r);
-	h = Dy(screen->r) - ButtonSize - 4 - strsize.y;
-	csize = (w < h ? w : h) / size;
-	w = size*csize;
-	left = screen->r.min.x + (Dx(screen->r) - w)/2;
-
-	/* buttons top */
-	y = screen->r.min.y + h + 2 + strsize.y;
-
-	if(full){
-		/* background */
-		draw(screen, screen->r, colora, nil, ZP);
-
-		/* buttons */
-		x = left + (w - NumColors*ButtonSize)/2;
-		for(i = 0; i < NumColors; i++, x += ButtonSize){
-			buttons[i] = Rect(x, y, x+ButtonSize, y+ButtonSize);
-			draw(screen, buttons[i], colors[i], nil, ZP);
-		}
-	}
-
-	/* caption */
-	p.x = left + w/2 - strsize.x/2;
-	p.y = y - strsize.y;
-	string(screen, p, colorb, sp, f, s);
-
-	/* cells */
-	c = cells;
-	for(x = 0; x < size; x++){
-		for(y = 0; y < size; y++, c++){
-			if((*c & Redraw) != 0 || full){
-				*c &= ~Redraw;
-				r.min.x = left + x*csize;
-				r.min.y = screen->r.min.y + 2 + y*csize;
-				r.max.x = r.min.x + csize;
-				r.max.y = r.min.y + csize;
-				draw(screen, r, colors[*c & ColorMask], nil, ZP);
-			}
-		}
-	}
-
-	flushimage(display, 1);
-}
-
-static void
-floodrecurse(uchar color, int x, int y)
-{
-	uchar *c;
-	c = &cells[x + y*size];
-	if((*c & Flood) == 0 && (*c & ColorMask) == color){
-		floodneighbours(color, x, y);
-	}
-}
-
-static void
-floodneighbours(uchar color, int x, int y)
-{
-	cells[x + y*size] = color|Flood|Redraw;
-
-	if(x > 0)
-		floodrecurse(color, x-1, y);
-	if(x < size-1)
-		floodrecurse(color, x+1, y);
-	if(y > 0)
-		floodrecurse(color, x, y-1);
-	if(y < size-1)
-		floodrecurse(color, x, y+1);
-}
-
-static int
-reflood(uchar color)
-{
-	int n, x, y;
-
-	color &= ColorMask;
-
-	n = 0;
-	for(x = 0; x < size; x++){
-		for(y = 0; y < size; y++){
-			if(cells[x + y*size] & Flood){
-				floodneighbours(color, x, y);
-				n++;
-			}
-		}
-	}
-	return n;
-}
-
-static void
-flood(uchar color)
-{
-	int n;
-
-	if((cells[0] & Flood) != 0 && (cells[0] & ColorMask) == color)
-		return;
-
-	if(!turnsleft)
-		return;
-
-	turnsleft--;
-	n = reflood(color);
-
-	if(n == size*size){
-		state = Twin;
-		clickwait = 1;
-	}else if(!turnsleft){
-		state = Tfail;
-		clickwait = 1;
-	}
-
-	redraw(screen, 0);
-}
-
-static void
-newgame(int sid)
-{
-	uchar *c;
-	int i, maxsize;
-
-	state = Tgame;
-	size = sizes[sid];
-	turnsleft = turns[sid];
-	clickwait = 0;
-
-	if(cells == nil){
-		maxsize = (size > sizes[Slarge]) ? size : sizes[Slarge];
-		cells = malloc(maxsize*maxsize);
-	}
-
-	/* randomize */
-	c = cells;
-	for(i = 0; i < size*size; i++){
-		*c++ = nrand(NumColors);
-	}
-
-	cells[0] |= Flood|Redraw;
-	reflood(cells[0]);
-	redraw(screen, 1);
-}
-
-void
-eresized(int new)
-{
-	if(new && getwindow(display, Refnone) < 0)
-		sysfatal("can't reattach to window: %r");
-	redraw(screen, 1);
-}
-
-static void
-usage(void)
-{
-	fprint(2, "usage: cflood [-s size] [-t turns]\n");
-	exits("usage");
-}
-
-void
-main(int argc, char** argv)
-{
-	int key, p, i, oldbuttons, sidmax, inv;
-	Event e;
-	Mouse m;
-	Menu menu;
-	Rectangle r;
-
-	sid = Ssmall;
-	inv = 0;
-	ARGBEGIN{
-	case 'b':
-		inv = 1;
-		break;
-	case 's':
-		sid = Scustom;
-		sizes[sid] = atoi(ARGF());
-		if(sizes[sid] < 1)
-			usage();
-		break;
-	case 't':
-		sid = Scustom;
-		turns[sid] = atoi(ARGF());
-		if(turns[sid] < 1)
-			usage();
-		break;
-	default:
-		usage();
-	}ARGEND
-
-	if(initdraw(0, 0, "cflood") < 0)
-		sysfatal("initdraw failed");
-
-	r = Rect(0, 0, 1, 1);
-	for(i = 0; i < NumColors; i++)
-		colors[i] = allocimage(display, r, CMAP8, 1, srccolors[i]);
-
-	colora = inv ? display->black : display->white;
-	colorb = inv ? display->white : display->black;
-
-	einit(Emouse);
-	menu.item = mstr;
-	menu.lasthit = 0;
-	srand(time(0));
-
-	sidmax = (sid > Slarge) ? sid : Slarge;
-	if(sid == Scustom){
-		/* move "exit" and add "custom" size/turns */
-		sidmax = sid;
-		mstr[Scustom+1] = mstr[Scustom];
-		mstr[Scustom] = smprint("%dx%d / %d", sizes[sid], sizes[sid], turns[sid]);
-	}
-
-	newgame(sid);
-
-	for(oldbuttons = 0;;){
-		key = event(&e);
-		m = e.mouse;
-
-		if(key != Emouse)
-			continue;
-
-		if(m.buttons & 4){
-			p = emenuhit(3, &m, &menu);
-			if(p >= Ssmall && p <= sidmax)
-				newgame(sid = p);
-			else if(p > 0)
-				break;
-		}else if(clickwait && !oldbuttons && m.buttons){
-			newgame(sid);
-		}else if(m.buttons & 1){
-			for(i = 0; i < NumColors; i++){
-				if(ptinrect(m.xy, buttons[i])){
-					flood(i);
-					break;
-				}
-			}
-		}
-
-		oldbuttons = m.buttons;
-	}
-
-	exits(nil);
-}
--- a/games/cflood.man
+++ /dev/null
@@ -1,41 +1,0 @@
-.TH CFLOOD 1
-.SH NAME
-cflood \- a timewaster
-.SH SYNOPSIS
-.B cflood
-[
-.I -b
-]
-[
-.I -s size
-]
-[
-.I -t turns
-]
-.SH DESCRIPTION
-.I cflood
-is a game in which player must fill an area with one color in a limited number of turns.
-.PP
-The
-.B -b
-option reverses the color scheme for text and background.
-.PP
-The
-.B -s
-option sets the size of the area to
-.IR size
-x
-.IR size .
-.PP
-The
-.B -t
-option sets the number of
-.IR turns .
-.EE
-.PP
-There are three predefined area sizes in the game menu (invoked by button 3).
-.EE
-.SH SOURCE
-http://bitbucket.org/ftrvxmtrx/p9
-.SH BUGS
-Of course.
--- a/games/mkfile
+++ /dev/null
@@ -1,11 +1,0 @@
-</$objtype/mkfile
-MAN=/sys/man/1
-
-TARG=\
-	cflood\
-
-BIN=/$objtype/bin/games
-
-</sys/src/cmd/mkmany
-
-install: cflood.man
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,11 @@
+</$objtype/mkfile
+MAN=/sys/man/1
+
+TARG=\
+	cflood\
+
+BIN=/$objtype/bin/games
+
+</sys/src/cmd/mkmany
+
+install: cflood.man