shithub: puzzles

Download patch

ref: cec6a8217fa2ae90a72226959e215b663c88bc41
parent: fd304c53cc45dc05b3f95c20a466e20a7e1c9194
author: sirjofri <[email protected]>
date: Fri May 10 09:06:51 EDT 2024

adds mkfile and plan9.c (intermediate commit)

many things work, but some things don't. Needs menu.

--- /dev/null
+++ b/mkfile
@@ -1,0 +1,102 @@
+</$objtype/mkfile
+
+CFLAGS=$CFLAGS -p -I/sys/include/npe -D__plan9__ -D__${objtype}__ -DNO_TGMATH_H -I. -D__plan9_keep_main__
+
+TARG=\
+	blackbox\
+	bridges\
+	cube\
+	dominosa\
+	fifteen\
+	filling\
+	flip\
+	flood\
+	galaxies\
+	guess\
+	inertia\
+	keen\
+	lightup\
+	loopy\
+	magnets\
+	map\
+	mines\
+	mosaic\
+	net\
+	netslide\
+	nullgame\
+	palisade\
+	pattern\
+	pearl\
+	pegs\
+	range\
+	rect\
+	samegame\
+	signpost\
+	singles\
+	sixteen\
+	slant\
+	solo\
+	tents\
+	towers\
+	tracks\
+	twiddle\
+	undead\
+	unequal\
+	unruly\
+	untangle\
+
+OFILES=\
+	combi.$O\
+	divvy.$O\
+	drawing.$O\
+	dsf.$O\
+	findloop.$O\
+	grid.$O\
+	hat.$O\
+	latin.$O\
+	laydomino.$O\
+	loopgen.$O\
+	malloc.$O\
+	matching.$O\
+	midend.$O\
+	misc.$O\
+	penrose-legacy.$O\
+	penrose.$O\
+	plan9.$O\
+	printing.$O\
+	ps.$O\
+	random.$O\
+	sort.$O\
+	spectre.$O\
+	tdq.$O\
+	tree234.$O\
+	version.$O\
+
+HFILES=\
+	grid.h\
+	hat-internal.h\
+	hat-tables.h\
+	hat.h\
+	latin.h\
+	loopgen.h\
+	matching.h\
+	penrose-internal.h\
+	penrose-legacy.h\
+	penrose.h\
+	puzzles.h\
+	spectre-internal.h\
+	spectre-tables-auto.h\
+	spectre-tables-manual.h\
+	spectre.h\
+	tree234.h\
+	version.h
+
+LIB=\
+	auxiliary/hatgen.$O\
+
+BIN=/$objtype/bin/puzzles
+
+</sys/src/cmd/mkmany
+
+auxiliary/hatgen.$O: auxiliary/hatgen.c
+	$CC $CFLAGS -o $target auxiliary/hatgen.c
--- a/penrose-legacy.h
+++ b/penrose-legacy.h
@@ -22,6 +22,10 @@
 
 typedef struct vector vector;
 
+#ifdef __plan9__
+#pragma incomplete vector
+#endif
+
 double penrose_legacy_vx(vector *vs, int i);
 double penrose_legacy_vy(vector *vs, int i);
 
--- /dev/null
+++ b/plan9.c
@@ -1,0 +1,482 @@
+#include <npe.h>
+#include <draw.h>
+#include <event.h>
+
+#undef PI
+#include "puzzles.h"
+
+#ifdef COMBINED
+#error Plan 9 should not be COMBINED
+#endif
+
+struct frontend {
+	Image *image;
+	midend *me;
+	Image *background;
+	Image **colors;
+	int ncolors;
+	Point ZP;
+	int topbarh;
+};
+
+frontend *fe;
+
+void
+frontend_default_colour(frontend *fe, float *output)
+{
+	output[0] = .9;
+	output[1] = .9;
+	output[2] = .9;
+}
+
+void
+get_random_seed(void **randseed, int *randseedsize)
+{
+	long *t = malloc(sizeof(long));
+	assert(t);
+	time(t);
+	*randseed = (void*)t;
+	*randseedsize = sizeof(long);
+}
+
+void
+deactivate_timer(frontend *fe)
+{
+}
+
+void activate_timer(frontend *fe)
+{
+}
+
+void fatal(const char *fmt, ...)
+{
+    va_list ap;
+
+    fprint(2, "fatal error: ");
+
+    va_start(ap, fmt);
+    vfprint(2, fmt, ap);
+    va_end(ap);
+
+    fprint(2, "\n");
+    sysfatal("error");
+}
+
+#ifdef DEBUGGING
+void debug_printf(const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    vfprint(1, fmt, ap);
+    va_end(ap);
+}
+#endif
+
+void
+usage(void)
+{
+	fprint(2, "usage: %s [-ho] [--options]\n", argv0);
+	exits(nil);
+}
+
+static void p9_draw_text(void *handle, int x, int y, int fonttype, int fontsize, int align, int color, const char *text)
+{
+	frontend *fe = (frontend*)handle;
+	string(fe->image, addpt(fe->ZP, Pt(x, y)), fe->colors[color], ZP, font, text);
+}
+
+static void
+p9_draw_rect(void *handle, int x, int y, int w, int h, int color)
+{
+	frontend *fe = (frontend*)handle;
+	draw(fe->image, rectaddpt(Rect(x, y, x+w, y+h), fe->ZP), fe->colors[color], nil, ZP);
+}
+
+static void
+p9_draw_line(void *handle, int x1, int y1, int x2, int y2, int color)
+{
+	frontend *fe = (frontend*)handle;
+	line(fe->image, addpt(fe->ZP, Pt(x1, y1)), addpt(fe->ZP, Pt(x2, y2)), Endsquare, Endsquare, 1, fe->colors[color], ZP);
+}
+
+static void
+p9_draw_thick_line(void *handle, float thickness, float x1, float y1, float x2, float y2, int color)
+{
+	frontend *fe = (frontend*)handle;
+	line(fe->image, addpt(fe->ZP, Pt(x1, y1)), addpt(fe->ZP, Pt(x2, y2)), Endsquare, Endsquare, thickness, fe->colors[color], ZP);
+}
+
+static void
+p9_draw_poly(void *handle, const int *coords, int npoints, int fillcolor, int outlinecolor)
+{
+	Point *points;
+	frontend *fe = (frontend*)handle;
+	
+	points = malloc(npoints * sizeof(Point));
+	for (int i = 0; i < npoints; i++) {
+		points[i].x = coords[i*2+0] + fe->ZP.x;
+		points[i].y = coords[i*2+1] + fe->ZP.y;
+	}
+	
+	if (fillcolor > 0)
+		fillpoly(fe->image, points, npoints, 0, fe->colors[fillcolor], fe->ZP);
+	if (outlinecolor > 0)
+		poly(fe->image, points, npoints, Endsquare, Endsquare, 1, fe->colors[outlinecolor], fe->ZP);
+	
+	free(points);
+}
+
+static void
+p9_draw_circle(void *handle, int cx, int cy, int radius, int fillcolor, int outlinecolor)
+{
+	frontend *fe = (frontend*)handle;
+	Point c = addpt(fe->ZP, Pt(cx, cy));
+	fillellipse(fe->image, c, radius, radius, fe->colors[fillcolor], ZP);
+	ellipse(fe->image, c, radius, radius, 0, fe->colors[outlinecolor], ZP);
+}
+
+static void
+p9_draw_update(void *handle, int x, int y, int w, int h)
+{
+}
+
+static void
+p9_clip(void *handle, int x, int y, int w, int h)
+{
+}
+
+static void
+p9_unclip(void *handle)
+{
+}
+
+static void
+p9_start_draw(void *handle)
+{
+}
+
+static void
+p9_end_draw(void *handle)
+{
+}
+
+static void
+p9_status_bar(void *handle, const char *text)
+{
+	frontend *fe = (frontend*)handle;
+	draw(fe->image, Rect(fe->ZP.x+10, fe->image->r.max.y-20, fe->image->r.max.x, fe->image->r.max.y), fe->background, nil, ZP);
+	string(fe->image, Pt(fe->ZP.x+10, fe->image->r.max.y-20), display->black, ZP, font, text);
+}
+
+static blitter*
+p9_blitter_new(void *handle, int w, int h)
+{
+	return nil;
+}
+
+static void
+p9_blitter_free(void *handle, blitter *bl)
+{
+}
+
+static void
+p9_blitter_save(void *handle, blitter *bl, int x, int y)
+{
+}
+
+static void
+p9_blitter_load(void *handle, blitter *bl, int x, int y)
+{
+}
+
+static const drawing_api p9_drawing = {
+	p9_draw_text,
+	p9_draw_rect,
+	p9_draw_line,
+	p9_draw_poly,
+	p9_draw_circle,
+	p9_draw_update,
+	p9_clip,
+	p9_unclip,
+	p9_start_draw,
+	p9_end_draw,
+	p9_status_bar,
+	p9_blitter_new,
+	p9_blitter_free,
+	p9_blitter_save,
+	p9_blitter_load,
+	nil, nil, nil, nil, nil, nil, nil, nil, /* {begin,end}_{doc,page,puzzle}, line_width, line_dotted */
+	nil, /* text_fallback */
+#ifdef NO_THICK_LINE
+	nil,
+#else
+	p9_draw_thick_line,
+#endif
+};
+
+static int rgb2col(int r, int g, int b)
+{
+	return (r<<24) | (g<<16) | (b<<8) | 0xFF;
+}
+
+static frontend*
+new_window(void)
+{
+	frontend *fe;
+	
+	fe = mallocz(sizeof(frontend), 1);
+	if (!fe)
+		sysfatal("error: out of memory!");
+	
+	fe->me = midend_new(fe, &thegame, &p9_drawing, fe);
+	
+	return fe;
+}
+
+void
+initfe(frontend *fe)
+{
+	float *colors;
+	int ncolors;
+	int r, g, b;
+	int col;
+	float bgcol[3];
+	
+	fe->topbarh = 20;
+	fe->image = screen;
+	fe->ZP = screen->r.min;
+	fe->ZP.y += fe->topbarh;
+	
+	frontend_default_colour(fe, bgcol);
+	fe->background = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, rgb2col(bgcol[0]*255., bgcol[1]*255., bgcol[2]*255.));
+	
+	colors = midend_colours(fe->me, &ncolors);
+	fe->colors = mallocz(ncolors * sizeof(Image*), 1);
+	for (int i = 0; i < ncolors; i++) {
+		r = colors[i*3+0] * 255.;
+		g = colors[i*3+1] * 255.;
+		b = colors[i*3+2] * 255.;
+		fe->colors[i] = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, rgb2col(r, g, b));
+	}
+	free(colors);
+}
+
+void
+resize(void)
+{
+	int x, y;
+	x = screen->r.max.x - screen->r.min.x;
+	y = screen->r.max.y - screen->r.min.y;
+	
+	midend_size(fe->me, &x, &y, 1, 1.);
+}
+
+void
+redrawui(void)
+{
+	Point to = fe->ZP;
+	to.x = fe->image->r.max.x;
+	line(fe->image, fe->ZP, to, Endsquare, Endsquare, 0, display->black, ZP);
+}
+
+void
+eresized(int new)
+{
+	if (new && getwindow(display, Refnone) < 0) {
+		sysfatal("can't reattach to window: %r");
+	}
+	
+	fe->image = screen;
+	fe->ZP = screen->r.min;
+	fe->ZP.y += fe->topbarh;
+	draw(screen, screen->r, fe->background, nil, ZP);
+	resize();
+	midend_redraw(fe->me);
+	redrawui();
+}
+
+void
+keyboardev(int c, Event *ev)
+{
+	switch (c) {
+	case 'q':
+	case 127: /* DEL */
+		exits(nil);
+		break;
+	default:
+		if (c >= 0 && midend_process_key(fe->me, 0, 0, c) == PKR_QUIT) {
+			exits(nil);
+		}
+	}
+}
+
+void
+printoptions(config_item *c)
+{
+	char *t;
+	char *s = nil, *cnames[16], *ckws[16];
+	int n = 0, m;
+	config_item *cfg = midend_get_config(fe->me, CFG_PREFS, &t);
+	
+	print("Options:\n");
+	while (cfg->type != C_END) {
+		switch (cfg->type) {
+		case C_STRING:
+			s = cfg->u.string.sval;
+			break;
+		case C_BOOLEAN:
+			s = cfg->u.boolean.bval ? "1" : "0";
+			break;
+		case C_CHOICES:
+			print("      Choices:\n");
+			n = getfields(cfg->u.choices.choicenames, cnames, 16, 1, ":");
+			m = getfields(cfg->u.choices.choicekws, ckws, 16, 1, ":");
+			assert(n == m && cfg->u.choices.selected < n);
+			s = ckws[cfg->u.choices.selected];
+			break;
+		}
+		print("--%s=%s\n      %s\n", cfg->kw, s, cfg->name);
+		if (cfg->type == C_CHOICES) {
+			print("      Choices:\n");
+			for (int i = 0; i < n; i++) {
+				print("      %s: %s\n", ckws[i], cnames[i]);
+			}
+		}
+		cfg++;
+	}
+}
+
+void
+parseoption(config_item *cfg, char *keyval)
+{
+	char *arg[2];
+	int n;
+	
+	n = getfields(keyval, arg, 2, 1, "=");
+	if (n != 2)
+		usage(); // exits
+	
+	while (cfg && cfg->type != C_END)
+		if (strcmp(cfg->kw, arg[0]) != 0)
+			cfg++;
+	
+	if (!cfg || cfg->type == C_END) {
+		fprint(2, "no valid option\n");
+		return;
+	}
+	
+	print("%s : %s\n", cfg->kw, cfg->name);
+	return;
+	
+	switch (cfg->type) {
+	case C_STRING:
+		cfg->u.string.sval = arg[1];
+		print("is string");
+		break;
+	case C_BOOLEAN:
+		n = atoi(arg[1]);
+		print("is boolean");
+		cfg->u.boolean.bval = n ? 1 : 0;
+		break;
+	case C_CHOICES:
+		// TODO
+		print("is choices");
+		fprint(2, "not implemented yet!\n");
+		break;
+	case C_END:
+	default:
+		print("not found");
+		break;
+	}
+}
+
+void
+hittopbar(int x, int buttons)
+{
+	if (buttons&1) {
+		print("left mouse\n");
+	} else
+	if (buttons&2) {
+		print("middle mouse\n");
+	} else
+	if (buttons&4) {
+		print("right mouse\n");
+	} else /* no button at all */
+		return;
+	print("pos: %d\n", x);
+}
+
+void
+main(int argc, char **argv)
+{
+	Event ev;
+	int e;
+	int x, y;
+	char *s;
+	int doprintoptions = 0;
+	char *wintitle;
+	config_item *cfg;
+	int changedprefs = 0;
+	
+	fe = new_window();
+	
+	wintitle = nil;
+	cfg = midend_get_config(fe->me, CFG_SETTINGS, &wintitle);
+	
+	ARGBEGIN{
+	case 'h':
+		usage();
+		break;
+	case 'o':
+		doprintoptions++;
+		break;
+	case '-':
+		parseoption(cfg, ARGF());
+		changedprefs++;
+		break;
+	}ARGEND;
+	
+	if (changedprefs) {	
+		s = midend_set_config(fe->me, CFG_SETTINGS, cfg);
+		if (s) {
+			fprint(2, "error: %s\n", s);
+			exits("error");
+		}
+	}
+	
+	if (doprintoptions) {
+		printoptions(cfg);
+		exits(nil);
+	}
+	
+	if (initdraw(nil, nil, wintitle) < 0) {
+		sysfatal("initdraw failed: %r");
+	}
+	
+	initfe(fe);
+	midend_new_game(fe->me);
+	einit(Emouse|Ekeyboard);
+	eresized(0);
+	
+	for (;;) {
+		switch (event(&ev)) {
+		case Emouse:
+			x = ev.mouse.xy.x - fe->ZP.x;
+			y = ev.mouse.xy.y - fe->ZP.y;
+			if (y < fe->topbarh) {
+				hittopbar(x, ev.mouse.buttons);
+			}
+			if (ev.mouse.buttons&1) {
+				midend_process_key(fe->me, x, y, LEFT_BUTTON);
+			} else
+			if (ev.mouse.buttons&2) {
+				midend_process_key(fe->me, x, y, MIDDLE_BUTTON);
+			} else
+			if (ev.mouse.buttons&4) {
+				midend_process_key(fe->me, x, y, RIGHT_BUTTON);
+			}
+		case Ekeyboard:
+			keyboardev(ev.kbdc, &ev);
+		}
+	}
+}
--- a/puzzles.h
+++ b/puzzles.h
@@ -5,6 +5,12 @@
 #ifndef PUZZLES_PUZZLES_H
 #define PUZZLES_PUZZLES_H
 
+/* this is needed for type signatures, probably due to a bug
+ * related to the const specifier */
+#ifdef __plan9__
+#define const
+#endif
+
 #include <stdio.h>  /* for FILE */
 #include <stdlib.h> /* for size_t */
 #include <limits.h> /* for UINT_MAX */
@@ -820,5 +826,22 @@
 
 /* A little bit of help to lazy developers */
 #define DEFAULT_STATUSBAR_TEXT "Use status_bar() to fill this in."
+
+#ifdef __plan9__
+#pragma incomplete midend
+#pragma incomplete drawing
+#pragma incomplete DSF
+#pragma incomplete tdq
+#pragma incomplete blitter
+#pragma incomplete frontend
+#pragma incomplete random_state
+#pragma incomplete document
+#pragma incomplete game
+#pragma incomplete game_params
+#pragma incomplete game_ui
+#pragma incomplete game_state
+#pragma incomplete game_drawstate
+#pragma incomplete struct findloopstate
+#endif
 
 #endif /* PUZZLES_PUZZLES_H */
--- a/tree234.h
+++ b/tree234.h
@@ -39,6 +39,10 @@
  */
 typedef struct tree234_Tag tree234;
 
+#ifdef __plan9__
+#pragma incomplete tree234
+#endif
+
 typedef int (*cmpfn234)(void *, void *);
 
 typedef void *(*copyfn234)(void *state, void *element);