summaryrefslogtreecommitdiff
path: root/sys/src/games/turtle.c
diff options
context:
space:
mode:
authoraiju <devnull@localhost>2019-11-03 13:49:23 +0000
committeraiju <devnull@localhost>2019-11-03 13:49:23 +0000
commitae61eb9381f6b0c70e1c52bf2c2b7f4cd0b5bb6f (patch)
treec62b500d4d8714e56cdb7153fcbc3ab328aa0e76 /sys/src/games/turtle.c
parent37827f533bcfe73d8aff7088fbeee1eaa42e8094 (diff)
add games/linden and games/turtle
Diffstat (limited to 'sys/src/games/turtle.c')
-rw-r--r--sys/src/games/turtle.c199
1 files changed, 199 insertions, 0 deletions
diff --git a/sys/src/games/turtle.c b/sys/src/games/turtle.c
new file mode 100644
index 000000000..55d6c54c5
--- /dev/null
+++ b/sys/src/games/turtle.c
@@ -0,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();
+ }
+}