shithub: riscv

Download patch

ref: ae61eb9381f6b0c70e1c52bf2c2b7f4cd0b5bb6f
parent: 37827f533bcfe73d8aff7088fbeee1eaa42e8094
author: aiju <devnull@localhost>
date: Sun Nov 3 08:49:23 EST 2019

add games/linden and games/turtle

--- /dev/null
+++ b/sys/games/lib/linden/sierpinski
@@ -1,0 +1,7 @@
+A
+A: B-A-B
+B: A+B+A
+A = 'draw 1'
+B = 'draw 1'
++ = 'turn -60'
+- = 'turn 60'
--- /dev/null
+++ b/sys/games/lib/linden/tree
@@ -1,0 +1,9 @@
+0
+1: 11
+0: 1[0]0
+0 = 'draw 0.2'
+1 = 'draw 0.4'
+[ = 'push
+turn -45'
+] = 'pop
+turn 45'
--- /dev/null
+++ b/sys/src/games/linden.c
@@ -1,0 +1,198 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ctype.h>
+
+Biobuf *Bin;
+
+typedef struct Symbol Symbol;
+typedef struct SString SString;
+
+enum { TSTRING = -2 };
+
+struct Symbol {
+	Rune name;
+	SString *rule;
+	char *output;
+	Symbol *next;
+};
+
+struct SString {
+	int n;
+	Symbol **d;
+};
+#pragma varargck type "σ" SString*
+
+Symbol *syms;
+SString *sstring;
+char strbuf[1024];
+
+void *
+emalloc(ulong n)
+{
+	void *v;
+	
+	v = malloc(n);
+	if(v == nil) sysfatal("malloc: %r");
+	memset(v, 0, n);
+	setmalloctag(v, getcallerpc(&n));
+	return v;
+}
+
+void
+sstringaddsym(SString *a, Symbol *b)
+{
+	a->d = realloc(a->d, (a->n + 1) * sizeof(Symbol *));
+	a->d[a->n++] = b;
+}
+
+void
+sstringappend(SString *a, SString *b)
+{
+	a->d = realloc(a->d, (a->n + b->n) * sizeof(Symbol *));
+	memcpy(a->d + a->n, b->d, b->n * sizeof(Symbol *));
+	a->n += b->n;
+}
+
+Symbol *
+getsym(Rune name)
+{
+	Symbol **sp;
+	
+	for(sp = &syms; *sp != nil; sp = &(*sp)->next)
+		if(name == (*sp)->name)
+			return *sp;
+	*sp = emalloc(sizeof(Symbol));
+	(*sp)->name = name;
+	return *sp;
+}
+
+int peektok = -1;
+
+int
+lex(void)
+{
+	int c;
+	char *p;
+	
+	if(peektok >= 0){
+		c = peektok;
+		peektok = -1;
+		return c;
+	}
+	do
+		c = Bgetrune(Bin);
+	while(c >= 0 && c < 0x80 && isspace(c) && c != '\n');
+	if(c == '\''){
+		p = strbuf;
+		for(;;){
+			c = Bgetc(Bin);
+			if(c == '\'') break;
+			if(p < strbuf + sizeof(strbuf) - 1)
+				*p++ = c;
+		}
+		*p = 0;
+		return TSTRING;
+	}
+	return c;
+}
+
+int
+peek(void)
+{
+	if(peektok >= 0) return peektok;
+	return peektok = lex();
+}
+
+SString *
+symstring(void)
+{
+	int c;
+	SString *r;
+	
+	r = emalloc(sizeof(SString));
+	for(;;){
+		c = peek();
+		if(c == '\n' || c == ':')
+			break;
+		lex();
+		r->d = realloc(r->d, (r->n + 1) * sizeof(Symbol *));
+		r->d[r->n++] = getsym(c);
+	}
+	return r;
+}
+
+int
+fmtsstring(Fmt *f)
+{
+	SString *s;
+	int i;
+	
+	s = va_arg(f->args, SString *);
+	for(i = 0; i < s->n; i++)
+		fmtprint(f, "%C", s->d[i]->name);
+	return 0;
+}
+
+void
+syntax(void)
+{
+	sysfatal("syntax error");
+}
+
+void
+parse(void)
+{
+	Symbol *s;
+	int c;
+
+	sstring = symstring();
+	while(peek() > 0){
+		if(peek() == '\n') {lex(); continue;}
+		if(peek() == ':') syntax();
+		s = getsym(lex());
+		c = lex();
+		if(c == ':')
+			s->rule = symstring();
+		else if(c == '='){
+			if(lex() != TSTRING) syntax();
+			s->output = strdup(strbuf);
+		}else
+			syntax();
+		c = lex();
+		if(c != -1 && c != '\n') syntax();
+	}
+}
+
+SString *
+iterate(SString *in)
+{
+	SString *r;
+	int i;
+	
+	r = emalloc(sizeof(SString));
+	for(i = 0; i < in->n; i++)
+		if(in->d[i]->rule == nil)
+			sstringaddsym(r, in->d[i]);
+		else
+			sstringappend(r, in->d[i]->rule);
+	return r;
+}
+
+void
+main()
+{
+	int i, j;
+
+	fmtinstall(L'σ', fmtsstring);
+	Bin = Bfdopen(0, OREAD);
+	if(Bin == nil) sysfatal("Bfdopen: %r");
+	parse();
+	for(j = 0; j < 9; j++){
+		for(i = 0; i < sstring->n; i++)
+			if(sstring->d[i]->output != nil)
+				print("%s\n", sstring->d[i]->output);
+		print("end\n");
+		sstring = iterate(sstring);
+	}
+}
--- /dev/null
+++ b/sys/src/games/turtle.c
@@ -1,0 +1,199 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <draw.h>
+#include <event.h>
+#include <keyboard.h>
+
+Biobuf *bin;
+
+double px, py;
+double θ;
+
+double *stack;
+int sp;
+int stacksize;
+
+double *lines;
+int lp;
+int *frames;
+int fp;
+
+int curframe;
+
+double minx = -10, maxx = 10, miny = -10, maxy = 10;
+
+Point
+cvt(double x, double y)
+{
+	return Pt((x - minx) * Dx(screen->r) / (maxx - minx) + screen->r.min.x, (maxy - y) * Dy(screen->r) / (maxy - miny) + screen->r.min.y);
+}
+
+void
+opdraw(int, char **argv)
+{
+	double npx, npy, l;
+	
+	l = atof(argv[1]);
+	npx = px + sin(θ * PI / 180) * l;
+	npy = py + cos(θ * PI / 180) * l;
+	lines = realloc(lines, (lp + 4) * sizeof(double));
+	lines[lp++] = px;
+	lines[lp++] = py;
+	lines[lp++] = npx;
+	lines[lp++] = npy;
+	px = npx;
+	py = npy;
+}
+
+void
+opturn(int, char **argv)
+{
+	θ += atof(argv[1]);
+}
+
+void
+oppush(int, char **)
+{
+	if(sp + 3 > stacksize){
+		stack = realloc(stack, (stacksize + 3) * sizeof(double));
+		stacksize += 3;
+	}
+	stack[sp++] = px;
+	stack[sp++] = py;
+	stack[sp++] = θ;
+}
+
+void
+oppop(int, char **)
+{
+	if(sp == 0) sysfatal("stack underflow");
+	θ = stack[--sp];
+	py = stack[--sp];
+	px = stack[--sp];
+}
+
+void
+opend(int, char **)
+{
+	θ = 0;
+	px = 0;
+	py = 0;
+	frames = realloc(frames, (fp + 1) * sizeof(int));
+	frames[fp++] = lp;
+}
+
+typedef struct Cmd Cmd;
+struct Cmd {
+	char *name;
+	int nargs;
+	void (*op)(int, char**);
+};
+
+Cmd cmdtab[] = {
+	"draw", 1, opdraw,
+	"turn", 1, opturn,
+	"push", 0, oppush,
+	"pop", 0, oppop,
+	"end", 0, opend,
+};
+
+void
+runline(char *s)
+{
+	char *f[10];
+	int nf;
+	Cmd *p;
+	
+	nf = tokenize(s, f, nelem(f));
+	if(nf == 0) return;
+	for(p = cmdtab; p < cmdtab + nelem(cmdtab); p++)
+		if(strcmp(p->name, f[0]) == 0){
+			if(nf != p->nargs + 1 && p->nargs >= 0)
+				sysfatal("wrong number of arguments for %s", f[0]);
+			p->op(nf, f);
+			return;
+		}
+	sysfatal("unknown command %s", f[0]);
+}
+
+void
+redraw(void)
+{
+	int i;
+
+	minx = maxx = lines[frames[curframe]];
+	miny = maxy = lines[frames[curframe]+1];
+	
+	for(i = frames[curframe]; i < frames[curframe + 1]; i += 2){
+		if(lines[i] < minx) minx = lines[i];
+		if(lines[i] > maxx) maxx = lines[i];
+		if(lines[i+1] < miny) miny = lines[i+1];
+		if(lines[i+1] > maxy) maxy = lines[i+1];
+	}
+	maxx += (maxx - minx) * 0.05;
+	minx -= (maxx - minx) * 0.05;
+	maxy += (maxy - miny) * 0.05;
+	miny -= (maxy - miny) * 0.05;
+	if(minx == maxx){ minx -= 0.05; maxx += 0.05; }
+	if(miny == maxy){ miny -= 0.05; maxy += 0.05; }
+	draw(screen, screen->r, display->white, nil, ZP);
+	for(i = frames[curframe]; i < frames[curframe + 1]; i += 4)
+		line(screen, cvt(lines[i], lines[i+1]), cvt(lines[i+2], lines[i+3]), 0, 0, 0, display->black, ZP);
+	flushimage(display, 1);
+}
+
+void
+eresized(int new)
+{
+	if(new && getwindow(display, Refnone) < 0){
+		fprint(2, "colors: can't reattach to window: %r\n");
+		exits("resized");
+	}
+	redraw();
+}
+
+void
+main()
+{
+	char *s;
+
+	bin = Bfdopen(0, OREAD);
+	if(bin == nil) sysfatal("Bfdopen: %r");
+	
+	frames = malloc(sizeof(int));
+	frames[fp++] = 0;
+		
+	for(;;){
+		s = Brdstr(bin, '\n', 1);
+		if(s == nil) break;
+		runline(s);
+	}
+
+	if(initdraw(nil, nil, nil) < 0)
+		sysfatal("initdraw: %r");
+	einit(Emouse | Ekeyboard);
+	
+	redraw();
+	for(;;){
+		switch(ekbd()){
+		case Khome:
+			curframe = 0;
+			break;
+		case Kend:
+			curframe = fp - 2;
+			break;
+		case Kup: case Kleft:
+			if(curframe > 0)
+				curframe--;
+			break;
+		case ' ': case Kdown: case Kright:
+			if(curframe < fp - 2)
+				curframe++;
+			break;
+		case 'q': case Kdel:
+			exits(nil);
+		}
+		redraw();
+	}
+}