]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/galaxy/mkgalaxy.c
games/galaxy: add n-body simulator
[plan9front.git] / sys / src / games / galaxy / mkgalaxy.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <draw.h>
5 #include "galaxy.h"
6
7 Vector o, gv;
8 double
9         d = 100, drand,
10         sz = 25, szrand,
11         v, vrand,
12         av, avrand;
13 int new, c = 1;
14
15 void quadcalc(QB, Body*, double){}
16 Image *randcol(void){ return nil; }
17
18 void
19 usage(void)
20 {
21         fprint(2, "Usage: %s [-d dist[±r]]\n\t[-s size[±r]] [-v vel[±r]]\n\t[-av angvel[±r]] [-gv xdir,ydir]\n\t[-o xoff,yoff] [-f file]\n\t[-sq] [-i] size\n", argv0);
22         exits("usage");
23 }
24
25 Vector
26 polar(double ang, double mag)
27 {
28         Vector v;
29
30         v.x = cos(ang)*mag;
31         v.y = sin(ang)*mag;
32         return v;
33 }
34
35 Vector
36 getvec(char *str)
37 {
38         Vector v;
39
40         v.x = strtod(str, &str);
41         if(*str != ',')
42                 usage();
43         v.y = strtod(str+1, nil);
44         return v;
45 }
46
47 double
48 getvals(char *str, double *rand)
49 {
50         Rune r;
51         double val;
52         int i;
53
54         val = strtod(str, &str);
55         i = chartorune(&r, str);
56         if(r == L'±')
57                 *rand = strtod(str+i, nil);
58         else
59                 *rand = 0;
60         return val;
61 }
62
63 #define RAND(r) ((r)*(frand()*2 - 1))
64
65 void
66 mkbodies(double lim)
67 {
68         Body *b;
69         Vector p;
70         double x, y;
71
72         for(x = -lim/2; x < lim/2; x += d)
73         for(y = -lim/2; y < lim/2; y += d) {
74                 p.x = x + RAND(drand);
75                 p.y = y + RAND(drand);
76                 if(c)
77                 if(hypot(p.x, p.y) > lim/2)
78                         continue;
79                 b = body();
80                 b->Vector = p;
81                 b->v = polar(frand()*π2, v+RAND(vrand));
82                 b->v.x += gv.x - p.y*(av + RAND(avrand))/1000;
83                 b->v.y += gv.y + p.x*(av + RAND(avrand))/1000;
84                 b->size = sz + RAND(szrand);
85         }
86 }
87
88 void
89 main(int argc, char **argv)
90 {
91         static Biobuf bout;
92         Body *b;
93         double lim;
94         int fd;
95         char *a;
96
97         srand(truerand());
98         fmtinstall('B', Bfmt);
99         glxyinit();
100
101         ARGBEGIN {
102         case 'f':
103                 fd = open(EARGF(usage()), OREAD);
104                 if(fd < 0)
105                         sysfatal("Could not open file %s: %r", *argv);
106                 readglxy(fd);
107                 close(fd);
108                 break;
109         case 'i':
110                 readglxy(0);
111                 break;
112         case 's':
113                 a = EARGF(usage());
114                 switch(a[0]) {
115                 case 'q':
116                         if(a[1] != '\0')
117                                 usage();
118                         c = 0;
119                         break;
120                 default:
121                         sz = getvals(a, &szrand);
122                         break;
123                 }
124                 break;
125         case 'a':
126                 a = EARGF(usage());
127                 if(a[0] != 'v' || a[1] != '\0')
128                         usage();
129                 argc--;
130                 argv++;
131                 av = getvals(*argv, &avrand);
132                 break;
133         case 'g':
134                 a = EARGF(usage());
135                 if(a[0] != 'v' || a[1] != '\0')
136                         usage();
137                 argc--;
138                 argv++;
139                 gv = getvec(*argv);
140                 break;
141         case 'v':
142                 v = getvals(EARGF(usage()), &vrand);
143                 break;
144         case 'o':
145                 o = getvec(EARGF(usage()));
146                 break;
147         case 'd':
148                 d = getvals(EARGF(usage()), &drand);
149                 break;
150         } ARGEND
151
152         if(argc != 1)
153                 usage();
154
155         new = glxy.l;
156         lim = strtod(*argv, nil);
157         mkbodies(lim);
158
159         Binit(&bout, 1, OWRITE);
160         for(b = glxy.a; b < glxy.a + new; b++)
161                 Bprint(&bout, "%B\n", b);
162
163         for(b = glxy.a+new; b < glxy.a+glxy.l; b++) {
164                 b->x += o.x;
165                 b->y += o.y;
166                 Bprint(&bout, "%B\n", b);
167         }
168         Bterm(&bout);
169
170         exits(nil);
171 }