shithub: cflood

Download patch

ref: 8d4482800b46dbcdb67d49d9ba35bf0a03aa205c
author: Sigrid Solveig Haflínudóttir <[email protected]>
date: Thu Dec 13 08:48:34 EST 2012

games/cflood. unfinished yet

diff: cannot open b/games//null: file does not exist: 'b/games//null'
--- /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