add games/linden and games/turtle
This commit is contained in:
parent
37827f533b
commit
ae61eb9381
4 changed files with 413 additions and 0 deletions
7
sys/games/lib/linden/sierpinski
Normal file
7
sys/games/lib/linden/sierpinski
Normal file
|
@ -0,0 +1,7 @@
|
|||
A
|
||||
A: B-A-B
|
||||
B: A+B+A
|
||||
A = 'draw 1'
|
||||
B = 'draw 1'
|
||||
+ = 'turn -60'
|
||||
- = 'turn 60'
|
9
sys/games/lib/linden/tree
Normal file
9
sys/games/lib/linden/tree
Normal file
|
@ -0,0 +1,9 @@
|
|||
0
|
||||
1: 11
|
||||
0: 1[0]0
|
||||
0 = 'draw 0.2'
|
||||
1 = 'draw 0.4'
|
||||
[ = 'push
|
||||
turn -45'
|
||||
] = 'pop
|
||||
turn 45'
|
198
sys/src/games/linden.c
Normal file
198
sys/src/games/linden.c
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
199
sys/src/games/turtle.c
Normal file
199
sys/src/games/turtle.c
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue