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
--- /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