]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/turtle.c
add games/linden and games/turtle
[plan9front.git] / sys / src / games / turtle.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <draw.h>
5 #include <event.h>
6 #include <keyboard.h>
7
8 Biobuf *bin;
9
10 double px, py;
11 double θ;
12
13 double *stack;
14 int sp;
15 int stacksize;
16
17 double *lines;
18 int lp;
19 int *frames;
20 int fp;
21
22 int curframe;
23
24 double minx = -10, maxx = 10, miny = -10, maxy = 10;
25
26 Point
27 cvt(double x, double y)
28 {
29         return Pt((x - minx) * Dx(screen->r) / (maxx - minx) + screen->r.min.x, (maxy - y) * Dy(screen->r) / (maxy - miny) + screen->r.min.y);
30 }
31
32 void
33 opdraw(int, char **argv)
34 {
35         double npx, npy, l;
36         
37         l = atof(argv[1]);
38         npx = px + sin(θ * PI / 180) * l;
39         npy = py + cos(θ * PI / 180) * l;
40         lines = realloc(lines, (lp + 4) * sizeof(double));
41         lines[lp++] = px;
42         lines[lp++] = py;
43         lines[lp++] = npx;
44         lines[lp++] = npy;
45         px = npx;
46         py = npy;
47 }
48
49 void
50 opturn(int, char **argv)
51 {
52         θ += atof(argv[1]);
53 }
54
55 void
56 oppush(int, char **)
57 {
58         if(sp + 3 > stacksize){
59                 stack = realloc(stack, (stacksize + 3) * sizeof(double));
60                 stacksize += 3;
61         }
62         stack[sp++] = px;
63         stack[sp++] = py;
64         stack[sp++] = θ;
65 }
66
67 void
68 oppop(int, char **)
69 {
70         if(sp == 0) sysfatal("stack underflow");
71         θ = stack[--sp];
72         py = stack[--sp];
73         px = stack[--sp];
74 }
75
76 void
77 opend(int, char **)
78 {
79         θ = 0;
80         px = 0;
81         py = 0;
82         frames = realloc(frames, (fp + 1) * sizeof(int));
83         frames[fp++] = lp;
84 }
85
86 typedef struct Cmd Cmd;
87 struct Cmd {
88         char *name;
89         int nargs;
90         void (*op)(int, char**);
91 };
92
93 Cmd cmdtab[] = {
94         "draw", 1, opdraw,
95         "turn", 1, opturn,
96         "push", 0, oppush,
97         "pop", 0, oppop,
98         "end", 0, opend,
99 };
100
101 void
102 runline(char *s)
103 {
104         char *f[10];
105         int nf;
106         Cmd *p;
107         
108         nf = tokenize(s, f, nelem(f));
109         if(nf == 0) return;
110         for(p = cmdtab; p < cmdtab + nelem(cmdtab); p++)
111                 if(strcmp(p->name, f[0]) == 0){
112                         if(nf != p->nargs + 1 && p->nargs >= 0)
113                                 sysfatal("wrong number of arguments for %s", f[0]);
114                         p->op(nf, f);
115                         return;
116                 }
117         sysfatal("unknown command %s", f[0]);
118 }
119
120 void
121 redraw(void)
122 {
123         int i;
124
125         minx = maxx = lines[frames[curframe]];
126         miny = maxy = lines[frames[curframe]+1];
127         
128         for(i = frames[curframe]; i < frames[curframe + 1]; i += 2){
129                 if(lines[i] < minx) minx = lines[i];
130                 if(lines[i] > maxx) maxx = lines[i];
131                 if(lines[i+1] < miny) miny = lines[i+1];
132                 if(lines[i+1] > maxy) maxy = lines[i+1];
133         }
134         maxx += (maxx - minx) * 0.05;
135         minx -= (maxx - minx) * 0.05;
136         maxy += (maxy - miny) * 0.05;
137         miny -= (maxy - miny) * 0.05;
138         if(minx == maxx){ minx -= 0.05; maxx += 0.05; }
139         if(miny == maxy){ miny -= 0.05; maxy += 0.05; }
140         draw(screen, screen->r, display->white, nil, ZP);
141         for(i = frames[curframe]; i < frames[curframe + 1]; i += 4)
142                 line(screen, cvt(lines[i], lines[i+1]), cvt(lines[i+2], lines[i+3]), 0, 0, 0, display->black, ZP);
143         flushimage(display, 1);
144 }
145
146 void
147 eresized(int new)
148 {
149         if(new && getwindow(display, Refnone) < 0){
150                 fprint(2, "colors: can't reattach to window: %r\n");
151                 exits("resized");
152         }
153         redraw();
154 }
155
156 void
157 main()
158 {
159         char *s;
160
161         bin = Bfdopen(0, OREAD);
162         if(bin == nil) sysfatal("Bfdopen: %r");
163         
164         frames = malloc(sizeof(int));
165         frames[fp++] = 0;
166                 
167         for(;;){
168                 s = Brdstr(bin, '\n', 1);
169                 if(s == nil) break;
170                 runline(s);
171         }
172
173         if(initdraw(nil, nil, nil) < 0)
174                 sysfatal("initdraw: %r");
175         einit(Emouse | Ekeyboard);
176         
177         redraw();
178         for(;;){
179                 switch(ekbd()){
180                 case Khome:
181                         curframe = 0;
182                         break;
183                 case Kend:
184                         curframe = fp - 2;
185                         break;
186                 case Kup: case Kleft:
187                         if(curframe > 0)
188                                 curframe--;
189                         break;
190                 case ' ': case Kdown: case Kright:
191                         if(curframe < fp - 2)
192                                 curframe++;
193                         break;
194                 case 'q': case Kdel:
195                         exits(nil);
196                 }
197                 redraw();
198         }
199 }