diff options
author | aiju <devnull@localhost> | 2019-11-03 13:49:23 +0000 |
---|---|---|
committer | aiju <devnull@localhost> | 2019-11-03 13:49:23 +0000 |
commit | ae61eb9381f6b0c70e1c52bf2c2b7f4cd0b5bb6f (patch) | |
tree | c62b500d4d8714e56cdb7153fcbc3ab328aa0e76 /sys/src/games | |
parent | 37827f533bcfe73d8aff7088fbeee1eaa42e8094 (diff) |
add games/linden and games/turtle
Diffstat (limited to 'sys/src/games')
-rw-r--r-- | sys/src/games/linden.c | 198 | ||||
-rw-r--r-- | sys/src/games/turtle.c | 199 |
2 files changed, 397 insertions, 0 deletions
diff --git a/sys/src/games/linden.c b/sys/src/games/linden.c new file mode 100644 index 000000000..dd013c85f --- /dev/null +++ b/sys/src/games/linden.c @@ -0,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); + } +} 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(); + } +} |