ref: 8d4482800b46dbcdb67d49d9ba35bf0a03aa205c
author: Sigrid Solveig Haflínudóttir <[email protected]>
date: Thu Dec 13 08:48:34 EST 2012
games/cflood. unfinished yet
--- /dev/null
+++ b/LICENSE.MIT
@@ -1,0 +1,18 @@
+Copyright © 2012 Serge Zirukin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--- /dev/null
+++ b/games/cflood.c
@@ -1,0 +1,205 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <event.h>
+
+enum {
+ Ssmall,
+ Snormal,
+ Slarge,
+
+ Flood = 1<<7,
+ ColorMask = 0x0f,
+
+ NumColors = 6,
+
+ ButtonSize = 32
+};
+
+const int sizes[] = {14, 21, 28};
+const int turns[] = {25, 35, 50};
+const ulong srccolors[NumColors] = {
+ 0x6060a8ff,
+ 0xf6f61dff,
+ 0x46b0e0ff,
+ 0x7ea020ff,
+ 0xf070a0ff,
+ 0xdc4a20ff
+};
+char *mstr[] = {
+ "14x14 / 25",
+ "25x25 / 35",
+ "28x28 / 50",
+ "exit",
+ 0
+};
+
+static int size;
+static int wait4click;
+static int turnsleft;
+static uchar cells[28*28]; // enough for maximal size
+static Image *colors[NumColors];
+static Rectangle buttons[NumColors];
+
+static void
+floodneighbours(uchar color, int x, int y);
+
+static void
+redraw(Image *screen) {
+ Rectangle r = screen->r;
+ draw(screen, r, display->white, nil, ZP);
+
+ const uchar *cell = &cells[0];
+ int w = Dx(r), h = Dy(r) - ButtonSize - 2;
+ int c = (w < h ? w : h) / size;
+ w = c*size;
+
+ // cells
+ for(int x = r.min.x; x < r.min.x+size*c; x+=c) {
+ for(int y = r.min.y; y < r.min.y+size*c; y+=c) {
+ Rectangle r = Rect(x, y, x+c, y+c);
+ draw(screen, r, colors[*cell & ColorMask], nil, ZP);
+ cell++;
+ }
+ }
+
+ // buttons
+ int startx = r.min.x + (w/2) - NumColors*ButtonSize/2;
+ int y = r.min.y + h;
+ for(int i = 0, x = startx; i < NumColors; i++, x += ButtonSize) {
+ buttons[i] = Rect(x, y, x+ButtonSize, y+ButtonSize);
+ draw(screen, buttons[i], colors[i], nil, ZP);
+ }
+
+ flushimage(display, 1);
+}
+
+static void
+floodrecurse(uchar color, int x, int y) {
+ uchar *c = &cells[x + y*size];
+ if((*c & Flood) == 0 && (*c & ColorMask) == color) {
+ *c = color | Flood;
+ floodneighbours(color, x, y);
+ }
+}
+
+static void
+floodneighbours(uchar color, int x, int y) {
+ cells[x + y*size] = color | Flood;
+
+ 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) {
+ color &= ColorMask;
+
+ int n = 0;
+ for(int x = 0; x < size; x++)
+ for(int y = 0; y < size; y++)
+ if(cells[x + y*size] & Flood) {
+ floodneighbours(color, x, y);
+ n++;
+ }
+ return n;
+}
+
+static void
+flood(uchar color) {
+ if((cells[0] & Flood) != 0 && (cells[0] & ColorMask) == color)
+ return;
+
+ if(!turnsleft)
+ return;
+
+ int n = reflood(color);
+ redraw(screen);
+
+ if(n == size*size) {
+ // win
+ wait4click = 1;
+ } else if(--turnsleft == 0) {
+ // fail
+ wait4click = 1;
+ }
+}
+
+static void
+newgame(int sid) {
+ size = sizes[sid];
+ turnsleft = turns[sid];
+
+ // randomize
+ uchar *c = &cells[0];
+ for(int i = 0; i < size*size; i++) {
+ *c++ = nrand(NumColors);
+ }
+
+ cells[0] |= Flood;
+ reflood(cells[0]);
+ redraw(screen);
+}
+
+void
+eresized(int new)
+{
+ if(new && getwindow(display, Refnone) < 0)
+ fprint(2, "can't reattach to window");
+ redraw(screen);
+}
+
+void main(int, char**) {
+ Menu menu;
+
+ if(initdraw(0, 0, "cflood") < 0)
+ sysfatal("initdraw failed");
+
+ Rectangle r = Rect(0, 0, 1, 1);
+ for(int i = 0; i < NumColors; i++) {
+ colors[i] = allocimage(display, r, CMAP8, 1, srccolors[i]);
+ }
+
+ einit(Emouse);
+ menu.item = mstr;
+ menu.lasthit = 0;
+ srand(time(0));
+
+ int sid = Snormal;
+ newgame(sid);
+
+ for(int mold = 0;;) {
+ Event e;
+ int key = event(&e);
+ Mouse m = e.mouse;
+
+ if(key != Emouse)
+ continue;
+
+ if(m.buttons & 4) {
+ int p = emenuhit(3, &m, &menu);
+ if(p >= Ssmall && p <= Slarge)
+ newgame(sid = p);
+ else if(p > 0)
+ break;
+ } else if(wait4click && !mold && m.buttons != mold) {
+ wait4click = 0;
+ newgame(sid);
+ } else if(m.buttons & 1) {
+ for(int i = 0; i < NumColors; i++) {
+ if(ptinrect(m.xy, buttons[i])) {
+ flood(i);
+ break;
+ }
+ }
+ }
+
+ mold = m.buttons;
+ }
+}
--- /dev/null
+++ b/games/mkfile
@@ -1,0 +1,7 @@
+</$objtype/mkfile
+
+TARG=cflood
+OFILES=cflood.$O
+BIN=/$objtype/bin
+
+</sys/src/cmd/mkone