1*3e5d0078SDavid du Colombier #include <u.h>
2*3e5d0078SDavid du Colombier #include <libc.h>
3*3e5d0078SDavid du Colombier #include <draw.h>
4*3e5d0078SDavid du Colombier
5*3e5d0078SDavid du Colombier #define NPJW 48
6*3e5d0078SDavid du Colombier #define NSPLIT 6
7*3e5d0078SDavid du Colombier #define NDOT 14
8*3e5d0078SDavid du Colombier #define MAXTRACKS 128
9*3e5d0078SDavid du Colombier #define MINV 6
10*3e5d0078SDavid du Colombier #define PDUP 1 /* useful for debugging */
11*3e5d0078SDavid du Colombier
12*3e5d0078SDavid du Colombier #define nels(a) (sizeof(a) / sizeof(a[0]))
13*3e5d0078SDavid du Colombier #define imin(a,b) (((a) <= (b)) ? (a) : (b))
14*3e5d0078SDavid du Colombier #define imax(a,b) (((a) >= (b)) ? (a) : (b))
15*3e5d0078SDavid du Colombier #define sqr(x) ((x) * (x))
16*3e5d0078SDavid du Colombier
17*3e5d0078SDavid du Colombier typedef struct vector vector;
18*3e5d0078SDavid du Colombier struct vector
19*3e5d0078SDavid du Colombier {
20*3e5d0078SDavid du Colombier double x;
21*3e5d0078SDavid du Colombier double y;
22*3e5d0078SDavid du Colombier };
23*3e5d0078SDavid du Colombier
24*3e5d0078SDavid du Colombier typedef struct dot Dot;
25*3e5d0078SDavid du Colombier struct dot
26*3e5d0078SDavid du Colombier {
27*3e5d0078SDavid du Colombier Point pos;
28*3e5d0078SDavid du Colombier Point ivel;
29*3e5d0078SDavid du Colombier vector vel;
30*3e5d0078SDavid du Colombier double mass;
31*3e5d0078SDavid du Colombier int charge;
32*3e5d0078SDavid du Colombier int height; /* precalculated for speed */
33*3e5d0078SDavid du Colombier int width; /* precalculated for speed */
34*3e5d0078SDavid du Colombier int facei;
35*3e5d0078SDavid du Colombier int spin;
36*3e5d0078SDavid du Colombier Image *face;
37*3e5d0078SDavid du Colombier Image *faces[4];
38*3e5d0078SDavid du Colombier Image *mask;
39*3e5d0078SDavid du Colombier Image *masks[4];
40*3e5d0078SDavid du Colombier Image *save;
41*3e5d0078SDavid du Colombier int ntracks;
42*3e5d0078SDavid du Colombier Point track[MAXTRACKS];
43*3e5d0078SDavid du Colombier int next_clear;
44*3e5d0078SDavid du Colombier int next_write;
45*3e5d0078SDavid du Colombier };
46*3e5d0078SDavid du Colombier
47*3e5d0078SDavid du Colombier Dot dot[NDOT];
48*3e5d0078SDavid du Colombier Dot *edot = &dot[NDOT];
49*3e5d0078SDavid du Colombier int total_spin = 3;
50*3e5d0078SDavid du Colombier vector no_gravity;
51*3e5d0078SDavid du Colombier vector gravity =
52*3e5d0078SDavid du Colombier {
53*3e5d0078SDavid du Colombier 0.0,
54*3e5d0078SDavid du Colombier 1.0,
55*3e5d0078SDavid du Colombier };
56*3e5d0078SDavid du Colombier
57*3e5d0078SDavid du Colombier /* static Image *track; */
58*3e5d0078SDavid du Colombier static Image *im;
59*3e5d0078SDavid du Colombier static int track_length;
60*3e5d0078SDavid du Colombier static int track_width;
61*3e5d0078SDavid du Colombier static int iflag;
62*3e5d0078SDavid du Colombier static double k_floor = 0.9;
63*3e5d0078SDavid du Colombier Image *screen;
64*3e5d0078SDavid du Colombier
65*3e5d0078SDavid du Colombier #include "andrew.bits"
66*3e5d0078SDavid du Colombier #include "bart.bits"
67*3e5d0078SDavid du Colombier #include "bwk.bits"
68*3e5d0078SDavid du Colombier #include "dmr.bits"
69*3e5d0078SDavid du Colombier #include "doug.bits"
70*3e5d0078SDavid du Colombier #include "gerard.bits"
71*3e5d0078SDavid du Colombier #include "howard.bits"
72*3e5d0078SDavid du Colombier #include "ken.bits"
73*3e5d0078SDavid du Colombier #include "philw.bits"
74*3e5d0078SDavid du Colombier #include "pjw.bits"
75*3e5d0078SDavid du Colombier #include "presotto.bits"
76*3e5d0078SDavid du Colombier #include "rob.bits"
77*3e5d0078SDavid du Colombier #include "sean.bits"
78*3e5d0078SDavid du Colombier #include "td.bits"
79*3e5d0078SDavid du Colombier
80*3e5d0078SDavid du Colombier Image*
eallocimage(Display * d,Rectangle r,ulong chan,int repl,int col)81*3e5d0078SDavid du Colombier eallocimage(Display *d, Rectangle r, ulong chan, int repl, int col)
82*3e5d0078SDavid du Colombier {
83*3e5d0078SDavid du Colombier Image *i;
84*3e5d0078SDavid du Colombier i = allocimage(d, r, chan, repl, col);
85*3e5d0078SDavid du Colombier if(i == nil) {
86*3e5d0078SDavid du Colombier fprint(2, "cannot allocate image\n");
87*3e5d0078SDavid du Colombier exits("allocimage");
88*3e5d0078SDavid du Colombier }
89*3e5d0078SDavid du Colombier return i;
90*3e5d0078SDavid du Colombier }
91*3e5d0078SDavid du Colombier
92*3e5d0078SDavid du Colombier /*
93*3e5d0078SDavid du Colombier * p1 dot p2
94*3e5d0078SDavid du Colombier * inner product
95*3e5d0078SDavid du Colombier */
96*3e5d0078SDavid du Colombier static
97*3e5d0078SDavid du Colombier double
dotprod(vector * p1,vector * p2)98*3e5d0078SDavid du Colombier dotprod(vector *p1, vector *p2)
99*3e5d0078SDavid du Colombier {
100*3e5d0078SDavid du Colombier return p1->x * p2->x + p1->y * p2->y;
101*3e5d0078SDavid du Colombier }
102*3e5d0078SDavid du Colombier
103*3e5d0078SDavid du Colombier /*
104*3e5d0078SDavid du Colombier * r = p1 + p2
105*3e5d0078SDavid du Colombier */
106*3e5d0078SDavid du Colombier static
107*3e5d0078SDavid du Colombier void
vecaddpt(vector * r,vector * p1,vector * p2)108*3e5d0078SDavid du Colombier vecaddpt(vector *r, vector *p1, vector *p2)
109*3e5d0078SDavid du Colombier {
110*3e5d0078SDavid du Colombier r->x = p1->x + p2->x;
111*3e5d0078SDavid du Colombier r->y = p1->y + p2->y;
112*3e5d0078SDavid du Colombier }
113*3e5d0078SDavid du Colombier
114*3e5d0078SDavid du Colombier /*
115*3e5d0078SDavid du Colombier * r = p1 - p2
116*3e5d0078SDavid du Colombier */
117*3e5d0078SDavid du Colombier static
118*3e5d0078SDavid du Colombier void
vecsub(vector * r,vector * p1,vector * p2)119*3e5d0078SDavid du Colombier vecsub(vector *r, vector *p1, vector *p2)
120*3e5d0078SDavid du Colombier {
121*3e5d0078SDavid du Colombier r->x = p1->x - p2->x;
122*3e5d0078SDavid du Colombier r->y = p1->y - p2->y;
123*3e5d0078SDavid du Colombier }
124*3e5d0078SDavid du Colombier
125*3e5d0078SDavid du Colombier /*
126*3e5d0078SDavid du Colombier * r = v * s
127*3e5d0078SDavid du Colombier * multiplication of a vector by a scalar
128*3e5d0078SDavid du Colombier */
129*3e5d0078SDavid du Colombier static
130*3e5d0078SDavid du Colombier void
scalmult(vector * r,vector * v,double s)131*3e5d0078SDavid du Colombier scalmult(vector *r, vector *v, double s)
132*3e5d0078SDavid du Colombier {
133*3e5d0078SDavid du Colombier r->x = v->x * s;
134*3e5d0078SDavid du Colombier r->y = v->y * s;
135*3e5d0078SDavid du Colombier }
136*3e5d0078SDavid du Colombier
137*3e5d0078SDavid du Colombier static
138*3e5d0078SDavid du Colombier double
separation(Dot * p,Dot * q)139*3e5d0078SDavid du Colombier separation(Dot *p, Dot *q)
140*3e5d0078SDavid du Colombier {
141*3e5d0078SDavid du Colombier return sqrt((double)(sqr(q->pos.x - p->pos.x) + sqr(q->pos.y - p->pos.y)));
142*3e5d0078SDavid du Colombier }
143*3e5d0078SDavid du Colombier
144*3e5d0078SDavid du Colombier static
145*3e5d0078SDavid du Colombier int
close_enough(Dot * p,Dot * q,double * s)146*3e5d0078SDavid du Colombier close_enough(Dot *p, Dot *q, double *s)
147*3e5d0078SDavid du Colombier {
148*3e5d0078SDavid du Colombier int sepx;
149*3e5d0078SDavid du Colombier int width;
150*3e5d0078SDavid du Colombier int sepy;
151*3e5d0078SDavid du Colombier
152*3e5d0078SDavid du Colombier sepx = p->pos.x - q->pos.x;
153*3e5d0078SDavid du Colombier width = p->width;
154*3e5d0078SDavid du Colombier
155*3e5d0078SDavid du Colombier if (sepx < -width || sepx > width)
156*3e5d0078SDavid du Colombier return 0;
157*3e5d0078SDavid du Colombier
158*3e5d0078SDavid du Colombier sepy = p->pos.y - q->pos.y;
159*3e5d0078SDavid du Colombier
160*3e5d0078SDavid du Colombier if (sepy < -width || sepy > width)
161*3e5d0078SDavid du Colombier return 0;
162*3e5d0078SDavid du Colombier
163*3e5d0078SDavid du Colombier if ((*s = separation(p, q)) > (double)width)
164*3e5d0078SDavid du Colombier return 0;
165*3e5d0078SDavid du Colombier
166*3e5d0078SDavid du Colombier return 1;
167*3e5d0078SDavid du Colombier }
168*3e5d0078SDavid du Colombier
169*3e5d0078SDavid du Colombier static
170*3e5d0078SDavid du Colombier void
ptov(vector * v,Point * p)171*3e5d0078SDavid du Colombier ptov(vector *v, Point *p)
172*3e5d0078SDavid du Colombier {
173*3e5d0078SDavid du Colombier v->x = (double)p->x;
174*3e5d0078SDavid du Colombier v->y = (double)p->y;
175*3e5d0078SDavid du Colombier }
176*3e5d0078SDavid du Colombier
177*3e5d0078SDavid du Colombier static
178*3e5d0078SDavid du Colombier void
vtop(Point * p,vector * v)179*3e5d0078SDavid du Colombier vtop(Point *p, vector *v)
180*3e5d0078SDavid du Colombier {
181*3e5d0078SDavid du Colombier p->x = (int)(v->x + 0.5);
182*3e5d0078SDavid du Colombier p->y = (int)(v->y + 0.5);
183*3e5d0078SDavid du Colombier }
184*3e5d0078SDavid du Colombier
185*3e5d0078SDavid du Colombier static
186*3e5d0078SDavid du Colombier void
exchange_spin(Dot * p,Dot * q)187*3e5d0078SDavid du Colombier exchange_spin(Dot *p, Dot *q)
188*3e5d0078SDavid du Colombier {
189*3e5d0078SDavid du Colombier int tspin;
190*3e5d0078SDavid du Colombier
191*3e5d0078SDavid du Colombier if (p->spin == 0 && q->spin == 0)
192*3e5d0078SDavid du Colombier return;
193*3e5d0078SDavid du Colombier
194*3e5d0078SDavid du Colombier tspin = p->spin + q->spin;
195*3e5d0078SDavid du Colombier
196*3e5d0078SDavid du Colombier p->spin = imax(nrand(imin(3, tspin + 1)), tspin + 1 - 3);
197*3e5d0078SDavid du Colombier
198*3e5d0078SDavid du Colombier if (p->spin == 0)
199*3e5d0078SDavid du Colombier {
200*3e5d0078SDavid du Colombier p->face = p->faces[0];
201*3e5d0078SDavid du Colombier p->mask = p->masks[0];
202*3e5d0078SDavid du Colombier }
203*3e5d0078SDavid du Colombier
204*3e5d0078SDavid du Colombier q->spin = tspin - p->spin;
205*3e5d0078SDavid du Colombier
206*3e5d0078SDavid du Colombier if (q->spin == 0)
207*3e5d0078SDavid du Colombier {
208*3e5d0078SDavid du Colombier q->face = q->faces[0];
209*3e5d0078SDavid du Colombier q->mask = q->masks[0];
210*3e5d0078SDavid du Colombier }
211*3e5d0078SDavid du Colombier }
212*3e5d0078SDavid du Colombier
213*3e5d0078SDavid du Colombier static
214*3e5d0078SDavid du Colombier void
exchange_charge(Dot * p,Dot * q)215*3e5d0078SDavid du Colombier exchange_charge(Dot *p, Dot *q)
216*3e5d0078SDavid du Colombier {
217*3e5d0078SDavid du Colombier if (p->charge == 0 && q->charge == 0)
218*3e5d0078SDavid du Colombier {
219*3e5d0078SDavid du Colombier switch (nrand(16))
220*3e5d0078SDavid du Colombier {
221*3e5d0078SDavid du Colombier case 0:
222*3e5d0078SDavid du Colombier p->charge = 1;
223*3e5d0078SDavid du Colombier q->charge = -1;
224*3e5d0078SDavid du Colombier break;
225*3e5d0078SDavid du Colombier
226*3e5d0078SDavid du Colombier case 1:
227*3e5d0078SDavid du Colombier p->charge = -1;
228*3e5d0078SDavid du Colombier q->charge = 1;
229*3e5d0078SDavid du Colombier break;
230*3e5d0078SDavid du Colombier }
231*3e5d0078SDavid du Colombier }
232*3e5d0078SDavid du Colombier }
233*3e5d0078SDavid du Colombier
234*3e5d0078SDavid du Colombier /*
235*3e5d0078SDavid du Colombier * The aim is to completely determine the final
236*3e5d0078SDavid du Colombier * velocities of the two interacting particles as
237*3e5d0078SDavid du Colombier * a function of their initial velocities, masses
238*3e5d0078SDavid du Colombier * and point of collision. We start with the two
239*3e5d0078SDavid du Colombier * quantities that we know are conserved in
240*3e5d0078SDavid du Colombier * elastic collisions -- momentum and kinetic energy.
241*3e5d0078SDavid du Colombier *
242*3e5d0078SDavid du Colombier * Let the masses of the particles be m1 and m2;
243*3e5d0078SDavid du Colombier * their initial velocities V1 and V2 (vector quantities
244*3e5d0078SDavid du Colombier * represented by upper case variables, scalars lower
245*3e5d0078SDavid du Colombier * case); their final velocities V1' and V2'.
246*3e5d0078SDavid du Colombier *
247*3e5d0078SDavid du Colombier * Conservation of momentum gives us:
248*3e5d0078SDavid du Colombier *
249*3e5d0078SDavid du Colombier * (1) m1 * V1 + m2 * V2 = m1 * V1' + m2 * V2'
250*3e5d0078SDavid du Colombier *
251*3e5d0078SDavid du Colombier * and conservation of kinetic energy gives:
252*3e5d0078SDavid du Colombier *
253*3e5d0078SDavid du Colombier * (2) 1/2 * m1 * |V1| * |V1| + 1/2 * m2 * |V2| * |V2| =
254*3e5d0078SDavid du Colombier * 1/2 * m1 * |V1'| * |V1'| + 1/2 * m2 * |V2'| * |V2'|
255*3e5d0078SDavid du Colombier *
256*3e5d0078SDavid du Colombier * Then, decomposing (1) into its 2D scalar components:
257*3e5d0078SDavid du Colombier *
258*3e5d0078SDavid du Colombier * (1a) m1 * v1x + m2 * v2x = m1 * v1x' + m2 * v2x'
259*3e5d0078SDavid du Colombier * (1b) m1 * v1y + m2 * v2y = m1 * v1y' + m2 * v2y'
260*3e5d0078SDavid du Colombier *
261*3e5d0078SDavid du Colombier * and simplifying and expanding (2):
262*3e5d0078SDavid du Colombier *
263*3e5d0078SDavid du Colombier * (2a) m1 * (v1x * v1x + v1y * v1y) +
264*3e5d0078SDavid du Colombier * m2 * (v2x * v2x + v2y * v2y)
265*3e5d0078SDavid du Colombier * =
266*3e5d0078SDavid du Colombier * m1 * (v1x' * v1x' + v1y' * v1y') +
267*3e5d0078SDavid du Colombier * m2 * (v2x' * v2x' + v2y' * v2y')
268*3e5d0078SDavid du Colombier *
269*3e5d0078SDavid du Colombier * We know m1, m2, V1 and V2 which leaves four unknowns:
270*3e5d0078SDavid du Colombier *
271*3e5d0078SDavid du Colombier * v1x', v1y', v2x' and v2y'
272*3e5d0078SDavid du Colombier *
273*3e5d0078SDavid du Colombier * but we have just three equations:
274*3e5d0078SDavid du Colombier *
275*3e5d0078SDavid du Colombier * (1a), (1b) and (2a)
276*3e5d0078SDavid du Colombier *
277*3e5d0078SDavid du Colombier * To remove this extra degree of freedom we add the assumption that
278*3e5d0078SDavid du Colombier * the forces during the collision act instantaneously and exactly
279*3e5d0078SDavid du Colombier * along the (displacement) vector joining the centres of the two objects.
280*3e5d0078SDavid du Colombier *
281*3e5d0078SDavid du Colombier * And unfortunately, I've forgotten the extra equation that this
282*3e5d0078SDavid du Colombier * adds to the system(!), but it turns out that this extra constraint
283*3e5d0078SDavid du Colombier * does allow us to solve the augmented system of equations.
284*3e5d0078SDavid du Colombier * (I guess I could reverse engineer it from the code ...)
285*3e5d0078SDavid du Colombier */
286*3e5d0078SDavid du Colombier static
287*3e5d0078SDavid du Colombier void
rebound(Dot * p,Dot * q,double s)288*3e5d0078SDavid du Colombier rebound(Dot *p, Dot *q, double s)
289*3e5d0078SDavid du Colombier {
290*3e5d0078SDavid du Colombier vector pposn;
291*3e5d0078SDavid du Colombier vector qposn;
292*3e5d0078SDavid du Colombier vector pvel;
293*3e5d0078SDavid du Colombier vector qvel;
294*3e5d0078SDavid du Colombier vector newqp; /* vector difference of the positions */
295*3e5d0078SDavid du Colombier vector newqpu; /* unit vector parallel to newqp */
296*3e5d0078SDavid du Colombier vector newqv; /* " " " " velocities */
297*3e5d0078SDavid du Colombier double projp; /* projection of p's velocity in newqp direction */
298*3e5d0078SDavid du Colombier double projq; /* " " q's velocity in newqp direction */
299*3e5d0078SDavid du Colombier double pmass; /* mass of p */
300*3e5d0078SDavid du Colombier double qmass; /* mass of q */
301*3e5d0078SDavid du Colombier double tmass; /* sum of mass of p and q */
302*3e5d0078SDavid du Colombier double dmass; /* difference of mass of p and q */
303*3e5d0078SDavid du Colombier double newp;
304*3e5d0078SDavid du Colombier double newq;
305*3e5d0078SDavid du Colombier
306*3e5d0078SDavid du Colombier if (s == 0.0)
307*3e5d0078SDavid du Colombier return;
308*3e5d0078SDavid du Colombier
309*3e5d0078SDavid du Colombier ptov(&pposn, &p->pos);
310*3e5d0078SDavid du Colombier ptov(&qposn, &q->pos);
311*3e5d0078SDavid du Colombier pvel = p->vel;
312*3e5d0078SDavid du Colombier qvel = q->vel;
313*3e5d0078SDavid du Colombier
314*3e5d0078SDavid du Colombier /*
315*3e5d0078SDavid du Colombier * Transform so that p is stationary at (0,0,0);
316*3e5d0078SDavid du Colombier */
317*3e5d0078SDavid du Colombier vecsub(&newqp, &qposn, &pposn);
318*3e5d0078SDavid du Colombier vecsub(&newqv, &qvel, &pvel);
319*3e5d0078SDavid du Colombier
320*3e5d0078SDavid du Colombier scalmult(&newqpu, &newqp, -1.0 / s);
321*3e5d0078SDavid du Colombier
322*3e5d0078SDavid du Colombier if (dotprod(&newqv, &newqpu) <= 0.0)
323*3e5d0078SDavid du Colombier return;
324*3e5d0078SDavid du Colombier
325*3e5d0078SDavid du Colombier projp = dotprod(&pvel, &newqpu);
326*3e5d0078SDavid du Colombier projq = dotprod(&qvel, &newqpu);
327*3e5d0078SDavid du Colombier pmass = p->mass;
328*3e5d0078SDavid du Colombier qmass = q->mass;
329*3e5d0078SDavid du Colombier tmass = pmass + qmass;
330*3e5d0078SDavid du Colombier dmass = pmass - qmass;
331*3e5d0078SDavid du Colombier newp = (2.0 * qmass * projq + dmass * projp) / tmass;
332*3e5d0078SDavid du Colombier newq = (2.0 * pmass * projp - dmass * projq) / tmass;
333*3e5d0078SDavid du Colombier scalmult(&newqp, &newqpu, projp - newp);
334*3e5d0078SDavid du Colombier scalmult(&newqv, &newqpu, projq - newq);
335*3e5d0078SDavid du Colombier vecsub(&pvel, &pvel, &newqp);
336*3e5d0078SDavid du Colombier vecsub(&qvel, &qvel, &newqv);
337*3e5d0078SDavid du Colombier
338*3e5d0078SDavid du Colombier p->vel = pvel;
339*3e5d0078SDavid du Colombier vtop(&p->ivel, &p->vel);
340*3e5d0078SDavid du Colombier q->vel = qvel;
341*3e5d0078SDavid du Colombier vtop(&q->ivel, &q->vel);
342*3e5d0078SDavid du Colombier
343*3e5d0078SDavid du Colombier exchange_spin(p, q);
344*3e5d0078SDavid du Colombier
345*3e5d0078SDavid du Colombier if (iflag)
346*3e5d0078SDavid du Colombier exchange_charge(p, q);
347*3e5d0078SDavid du Colombier }
348*3e5d0078SDavid du Colombier
349*3e5d0078SDavid du Colombier static
350*3e5d0078SDavid du Colombier int
rrand(int lo,int hi)351*3e5d0078SDavid du Colombier rrand(int lo, int hi)
352*3e5d0078SDavid du Colombier {
353*3e5d0078SDavid du Colombier return lo + nrand(hi + 1 - lo);
354*3e5d0078SDavid du Colombier }
355*3e5d0078SDavid du Colombier
356*3e5d0078SDavid du Colombier static
357*3e5d0078SDavid du Colombier void
drawdot(Dot * d)358*3e5d0078SDavid du Colombier drawdot(Dot *d)
359*3e5d0078SDavid du Colombier {
360*3e5d0078SDavid du Colombier Rectangle r;
361*3e5d0078SDavid du Colombier char buf[10];
362*3e5d0078SDavid du Colombier
363*3e5d0078SDavid du Colombier r = d->face->r;
364*3e5d0078SDavid du Colombier r = rectsubpt(r, d->face->r.min);
365*3e5d0078SDavid du Colombier r = rectaddpt(r, d->pos);
366*3e5d0078SDavid du Colombier r = rectaddpt(r, screen->r.min);
367*3e5d0078SDavid du Colombier
368*3e5d0078SDavid du Colombier draw(screen, r, d->face, d->mask, d->face->r.min);
369*3e5d0078SDavid du Colombier
370*3e5d0078SDavid du Colombier if(PDUP > 1) { /* assume debugging */
371*3e5d0078SDavid du Colombier sprint(buf, "(%d,%d)", d->pos.x, d->pos.y);
372*3e5d0078SDavid du Colombier string(screen, r.min, display->black, ZP, font, buf);
373*3e5d0078SDavid du Colombier }
374*3e5d0078SDavid du Colombier }
375*3e5d0078SDavid du Colombier
376*3e5d0078SDavid du Colombier static
377*3e5d0078SDavid du Colombier void
undraw(Dot * d)378*3e5d0078SDavid du Colombier undraw(Dot *d)
379*3e5d0078SDavid du Colombier {
380*3e5d0078SDavid du Colombier Rectangle r;
381*3e5d0078SDavid du Colombier r = d->face->r;
382*3e5d0078SDavid du Colombier r = rectsubpt(r, d->face->r.min);
383*3e5d0078SDavid du Colombier r = rectaddpt(r, d->pos);
384*3e5d0078SDavid du Colombier r = rectaddpt(r, screen->r.min);
385*3e5d0078SDavid du Colombier
386*3e5d0078SDavid du Colombier draw(screen, r, display->black, d->mask, d->face->r.min);
387*3e5d0078SDavid du Colombier
388*3e5d0078SDavid du Colombier /*
389*3e5d0078SDavid du Colombier if (track_width > 0)
390*3e5d0078SDavid du Colombier {
391*3e5d0078SDavid du Colombier if (d->ntracks >= track_length)
392*3e5d0078SDavid du Colombier {
393*3e5d0078SDavid du Colombier bitblt(&screen, d->track[d->next_clear], track, track->r, D ^ ~S);
394*3e5d0078SDavid du Colombier d->next_clear = (d->next_clear + 1) % track_length;
395*3e5d0078SDavid du Colombier d->ntracks--;
396*3e5d0078SDavid du Colombier }
397*3e5d0078SDavid du Colombier
398*3e5d0078SDavid du Colombier d->track[d->next_write] = Pt(d->pos.x + d->width / 2 - track_width / 2, d->pos.y + d->height / 2 - track_width / 2);
399*3e5d0078SDavid du Colombier bitblt(&screen, d->track[d->next_write], track, track->r, D ^ ~S);
400*3e5d0078SDavid du Colombier d->next_write = (d->next_write + 1) % track_length;
401*3e5d0078SDavid du Colombier d->ntracks++;
402*3e5d0078SDavid du Colombier }
403*3e5d0078SDavid du Colombier */
404*3e5d0078SDavid du Colombier }
405*3e5d0078SDavid du Colombier
406*3e5d0078SDavid du Colombier static void
copy(Image * a,Image * b)407*3e5d0078SDavid du Colombier copy(Image *a, Image *b)
408*3e5d0078SDavid du Colombier {
409*3e5d0078SDavid du Colombier if(PDUP==1 || eqrect(a->r, b->r))
410*3e5d0078SDavid du Colombier draw(a, a->r, b, nil, b->r.min);
411*3e5d0078SDavid du Colombier else {
412*3e5d0078SDavid du Colombier int x, y;
413*3e5d0078SDavid du Colombier for(x = a->r.min.x; x < a->r.max.x; x++)
414*3e5d0078SDavid du Colombier for(y = a->r.min.y; y < a->r.max.y; y++)
415*3e5d0078SDavid du Colombier draw(a, Rect(x,y,x+1,y+1), b, nil, Pt(x/PDUP,y/PDUP));
416*3e5d0078SDavid du Colombier }
417*3e5d0078SDavid du Colombier }
418*3e5d0078SDavid du Colombier
419*3e5d0078SDavid du Colombier static void
transpose(Image * b)420*3e5d0078SDavid du Colombier transpose(Image *b)
421*3e5d0078SDavid du Colombier {
422*3e5d0078SDavid du Colombier int x, y;
423*3e5d0078SDavid du Colombier
424*3e5d0078SDavid du Colombier for(x = b->r.min.x; x < b->r.max.x; x++)
425*3e5d0078SDavid du Colombier for(y = b->r.min.y; y < b->r.max.y; y++)
426*3e5d0078SDavid du Colombier draw(im, Rect(y,x,y+1,x+1), b, nil, Pt(x,y));
427*3e5d0078SDavid du Colombier
428*3e5d0078SDavid du Colombier draw(b, b->r, im, nil, ZP);
429*3e5d0078SDavid du Colombier }
430*3e5d0078SDavid du Colombier
431*3e5d0078SDavid du Colombier static void
reflect1_lr(Image * b)432*3e5d0078SDavid du Colombier reflect1_lr(Image *b)
433*3e5d0078SDavid du Colombier {
434*3e5d0078SDavid du Colombier int x;
435*3e5d0078SDavid du Colombier for(x = 0; x < PDUP*NPJW; x++)
436*3e5d0078SDavid du Colombier draw(im, Rect(x, 0, x, PDUP*NPJW), b, nil, Pt(b->r.max.x-x,0));
437*3e5d0078SDavid du Colombier draw(b, b->r, im, nil, ZP);
438*3e5d0078SDavid du Colombier }
439*3e5d0078SDavid du Colombier
440*3e5d0078SDavid du Colombier static void
reflect1_ud(Image * b)441*3e5d0078SDavid du Colombier reflect1_ud(Image *b)
442*3e5d0078SDavid du Colombier {
443*3e5d0078SDavid du Colombier int y;
444*3e5d0078SDavid du Colombier for(y = 0; y < PDUP*NPJW; y++)
445*3e5d0078SDavid du Colombier draw(im, Rect(0, y, PDUP*NPJW, y), b, nil, Pt(0,b->r.max.y-y));
446*3e5d0078SDavid du Colombier draw(b, b->r, im, nil, ZP);
447*3e5d0078SDavid du Colombier }
448*3e5d0078SDavid du Colombier
449*3e5d0078SDavid du Colombier static
450*3e5d0078SDavid du Colombier void
rotate_clockwise(Image * b)451*3e5d0078SDavid du Colombier rotate_clockwise(Image *b)
452*3e5d0078SDavid du Colombier {
453*3e5d0078SDavid du Colombier transpose(b);
454*3e5d0078SDavid du Colombier reflect1_lr(b);
455*3e5d0078SDavid du Colombier }
456*3e5d0078SDavid du Colombier
457*3e5d0078SDavid du Colombier static
458*3e5d0078SDavid du Colombier void
spin(Dot * d)459*3e5d0078SDavid du Colombier spin(Dot *d)
460*3e5d0078SDavid du Colombier {
461*3e5d0078SDavid du Colombier int i;
462*3e5d0078SDavid du Colombier
463*3e5d0078SDavid du Colombier if (d->spin > 0)
464*3e5d0078SDavid du Colombier {
465*3e5d0078SDavid du Colombier i = (d->facei + d->spin) % nels(d->faces);
466*3e5d0078SDavid du Colombier d->face = d->faces[i];
467*3e5d0078SDavid du Colombier d->mask = d->masks[i];
468*3e5d0078SDavid du Colombier d->facei = i;
469*3e5d0078SDavid du Colombier }
470*3e5d0078SDavid du Colombier sleep(0);
471*3e5d0078SDavid du Colombier }
472*3e5d0078SDavid du Colombier
473*3e5d0078SDavid du Colombier static
474*3e5d0078SDavid du Colombier void
restart(Dot * d)475*3e5d0078SDavid du Colombier restart(Dot *d)
476*3e5d0078SDavid du Colombier {
477*3e5d0078SDavid du Colombier static int beam;
478*3e5d0078SDavid du Colombier
479*3e5d0078SDavid du Colombier d->charge = 0;
480*3e5d0078SDavid du Colombier
481*3e5d0078SDavid du Colombier d->pos.x = 0;
482*3e5d0078SDavid du Colombier d->vel.x = 20.0 + (double)rrand(-2, 2);
483*3e5d0078SDavid du Colombier
484*3e5d0078SDavid du Colombier if (beam ^= 1)
485*3e5d0078SDavid du Colombier {
486*3e5d0078SDavid du Colombier d->pos.y = screen->r.max.y - d->height;
487*3e5d0078SDavid du Colombier d->vel.y = -20.0 + (double)rrand(-2, 2);
488*3e5d0078SDavid du Colombier }
489*3e5d0078SDavid du Colombier else
490*3e5d0078SDavid du Colombier {
491*3e5d0078SDavid du Colombier d->pos.y = 0;
492*3e5d0078SDavid du Colombier d->vel.y = 20.0 + (double)rrand(-2, 2);
493*3e5d0078SDavid du Colombier }
494*3e5d0078SDavid du Colombier
495*3e5d0078SDavid du Colombier vtop(&d->ivel, &d->vel);
496*3e5d0078SDavid du Colombier }
497*3e5d0078SDavid du Colombier
498*3e5d0078SDavid du Colombier static
499*3e5d0078SDavid du Colombier void
upd(Dot * d)500*3e5d0078SDavid du Colombier upd(Dot *d)
501*3e5d0078SDavid du Colombier {
502*3e5d0078SDavid du Colombier Dot *dd;
503*3e5d0078SDavid du Colombier
504*3e5d0078SDavid du Colombier spin(d);
505*3e5d0078SDavid du Colombier
506*3e5d0078SDavid du Colombier /*
507*3e5d0078SDavid du Colombier * Bounce off others?
508*3e5d0078SDavid du Colombier */
509*3e5d0078SDavid du Colombier for (dd = d + 1; dd != edot; dd++)
510*3e5d0078SDavid du Colombier {
511*3e5d0078SDavid du Colombier double s;
512*3e5d0078SDavid du Colombier
513*3e5d0078SDavid du Colombier if (close_enough(d, dd, &s))
514*3e5d0078SDavid du Colombier rebound(d, dd, s);
515*3e5d0078SDavid du Colombier }
516*3e5d0078SDavid du Colombier
517*3e5d0078SDavid du Colombier if (iflag)
518*3e5d0078SDavid du Colombier {
519*3e5d0078SDavid du Colombier /*
520*3e5d0078SDavid du Colombier * Going off-screen?
521*3e5d0078SDavid du Colombier */
522*3e5d0078SDavid du Colombier if
523*3e5d0078SDavid du Colombier (
524*3e5d0078SDavid du Colombier d->pos.x + d->width < 0
525*3e5d0078SDavid du Colombier ||
526*3e5d0078SDavid du Colombier d->pos.x >= Dx(screen->r)
527*3e5d0078SDavid du Colombier ||
528*3e5d0078SDavid du Colombier d->pos.y + d->height < 0
529*3e5d0078SDavid du Colombier ||
530*3e5d0078SDavid du Colombier d->pos.y >= Dy(screen->r)
531*3e5d0078SDavid du Colombier )
532*3e5d0078SDavid du Colombier restart(d);
533*3e5d0078SDavid du Colombier
534*3e5d0078SDavid du Colombier /*
535*3e5d0078SDavid du Colombier * Charge.
536*3e5d0078SDavid du Colombier */
537*3e5d0078SDavid du Colombier if (d->charge != 0)
538*3e5d0078SDavid du Colombier {
539*3e5d0078SDavid du Colombier /*
540*3e5d0078SDavid du Colombier * TODO: This is wrong -- should
541*3e5d0078SDavid du Colombier * generate closed paths. Can't
542*3e5d0078SDavid du Colombier * simulate effect of B field just
543*3e5d0078SDavid du Colombier * by adding in an orthogonal
544*3e5d0078SDavid du Colombier * velocity component... (sigh)
545*3e5d0078SDavid du Colombier */
546*3e5d0078SDavid du Colombier vector f;
547*3e5d0078SDavid du Colombier double s;
548*3e5d0078SDavid du Colombier
549*3e5d0078SDavid du Colombier f.x = -d->vel.y;
550*3e5d0078SDavid du Colombier f.y = d->vel.x;
551*3e5d0078SDavid du Colombier
552*3e5d0078SDavid du Colombier if ((s = sqrt(sqr(f.x) + sqr(f.y))) != 0.0)
553*3e5d0078SDavid du Colombier {
554*3e5d0078SDavid du Colombier scalmult(&f, &f, -((double)d->charge) / s);
555*3e5d0078SDavid du Colombier
556*3e5d0078SDavid du Colombier vecaddpt(&d->vel, &f, &d->vel);
557*3e5d0078SDavid du Colombier vtop(&d->ivel, &d->vel);
558*3e5d0078SDavid du Colombier }
559*3e5d0078SDavid du Colombier }
560*3e5d0078SDavid du Colombier }
561*3e5d0078SDavid du Colombier else
562*3e5d0078SDavid du Colombier {
563*3e5d0078SDavid du Colombier /*
564*3e5d0078SDavid du Colombier * Bounce off left or right border?
565*3e5d0078SDavid du Colombier */
566*3e5d0078SDavid du Colombier if (d->pos.x < 0)
567*3e5d0078SDavid du Colombier {
568*3e5d0078SDavid du Colombier d->vel.x = fabs(d->vel.x);
569*3e5d0078SDavid du Colombier vtop(&d->ivel, &d->vel);
570*3e5d0078SDavid du Colombier }
571*3e5d0078SDavid du Colombier else if (d->pos.x + d->width >= Dx(screen->r))
572*3e5d0078SDavid du Colombier {
573*3e5d0078SDavid du Colombier d->vel.x = -fabs(d->vel.x);
574*3e5d0078SDavid du Colombier vtop(&d->ivel, &d->vel);
575*3e5d0078SDavid du Colombier }
576*3e5d0078SDavid du Colombier
577*3e5d0078SDavid du Colombier /*
578*3e5d0078SDavid du Colombier * Bounce off top or bottom border?
579*3e5d0078SDavid du Colombier * (bottom is slightly inelastic)
580*3e5d0078SDavid du Colombier */
581*3e5d0078SDavid du Colombier if (d->pos.y < 0)
582*3e5d0078SDavid du Colombier {
583*3e5d0078SDavid du Colombier d->vel.y = fabs(d->vel.y);
584*3e5d0078SDavid du Colombier vtop(&d->ivel, &d->vel);
585*3e5d0078SDavid du Colombier }
586*3e5d0078SDavid du Colombier else if (d->pos.y + d->height >= Dy(screen->r))
587*3e5d0078SDavid du Colombier {
588*3e5d0078SDavid du Colombier if (gravity.y == 0.0)
589*3e5d0078SDavid du Colombier d->vel.y = -fabs(d->vel.y);
590*3e5d0078SDavid du Colombier else if (d->ivel.y >= -MINV && d->ivel.y <= MINV)
591*3e5d0078SDavid du Colombier {
592*3e5d0078SDavid du Colombier /*
593*3e5d0078SDavid du Colombier * y-velocity is too small --
594*3e5d0078SDavid du Colombier * give it a random kick.
595*3e5d0078SDavid du Colombier */
596*3e5d0078SDavid du Colombier d->vel.y = (double)-rrand(30, 40);
597*3e5d0078SDavid du Colombier d->vel.x = (double)rrand(-10, 10);
598*3e5d0078SDavid du Colombier }
599*3e5d0078SDavid du Colombier else
600*3e5d0078SDavid du Colombier d->vel.y = -fabs(d->vel.y) * k_floor;
601*3e5d0078SDavid du Colombier vtop(&d->ivel, &d->vel);
602*3e5d0078SDavid du Colombier }
603*3e5d0078SDavid du Colombier }
604*3e5d0078SDavid du Colombier
605*3e5d0078SDavid du Colombier if (gravity.x != 0.0 || gravity.y != 0.0)
606*3e5d0078SDavid du Colombier {
607*3e5d0078SDavid du Colombier vecaddpt(&d->vel, &gravity, &d->vel);
608*3e5d0078SDavid du Colombier vtop(&d->ivel, &d->vel);
609*3e5d0078SDavid du Colombier }
610*3e5d0078SDavid du Colombier
611*3e5d0078SDavid du Colombier d->pos = addpt(d->pos, d->ivel);
612*3e5d0078SDavid du Colombier
613*3e5d0078SDavid du Colombier drawdot(d);
614*3e5d0078SDavid du Colombier }
615*3e5d0078SDavid du Colombier
616*3e5d0078SDavid du Colombier static
617*3e5d0078SDavid du Colombier void
setup(Dot * d,char * who,uchar * face,int n_els)618*3e5d0078SDavid du Colombier setup(Dot *d, char *who, uchar *face, int n_els)
619*3e5d0078SDavid du Colombier {
620*3e5d0078SDavid du Colombier int i, j, k, n;
621*3e5d0078SDavid du Colombier int repl;
622*3e5d0078SDavid du Colombier uchar mask;
623*3e5d0078SDavid du Colombier int nbits, bits;
624*3e5d0078SDavid du Colombier uchar tmpface[NPJW*NPJW];
625*3e5d0078SDavid du Colombier uchar tmpmask[NPJW*NPJW];
626*3e5d0078SDavid du Colombier static Image *im; /* not the global */
627*3e5d0078SDavid du Colombier static Image *imask;
628*3e5d0078SDavid du Colombier
629*3e5d0078SDavid du Colombier if(im == nil)
630*3e5d0078SDavid du Colombier {
631*3e5d0078SDavid du Colombier im = eallocimage(display, Rect(0,0,NPJW,NPJW), CMAP8, 0, DNofill);
632*3e5d0078SDavid du Colombier imask = eallocimage(display, Rect(0,0,NPJW,NPJW), CMAP8, 0, DNofill);
633*3e5d0078SDavid du Colombier }
634*3e5d0078SDavid du Colombier
635*3e5d0078SDavid du Colombier repl = (NPJW*NPJW)/n_els;
636*3e5d0078SDavid du Colombier if(repl > 8) {
637*3e5d0078SDavid du Colombier fprint(2, "can't happen --rsc\n");
638*3e5d0078SDavid du Colombier exits("repl");
639*3e5d0078SDavid du Colombier }
640*3e5d0078SDavid du Colombier nbits = 8/repl;
641*3e5d0078SDavid du Colombier mask = (1<<(nbits))-1;
642*3e5d0078SDavid du Colombier
643*3e5d0078SDavid du Colombier if(0) print("converting %s... n_els=%d repl=%d mask=%x nbits=%d...\n",
644*3e5d0078SDavid du Colombier who, n_els, repl, mask, nbits);
645*3e5d0078SDavid du Colombier n = 0;
646*3e5d0078SDavid du Colombier for (i = 0; i < n_els; i++)
647*3e5d0078SDavid du Colombier {
648*3e5d0078SDavid du Colombier for(j = repl; j--; ) {
649*3e5d0078SDavid du Colombier bits = (face[i] >> (j*nbits)) & mask;
650*3e5d0078SDavid du Colombier tmpface[n] = 0;
651*3e5d0078SDavid du Colombier tmpmask[n] = 0;
652*3e5d0078SDavid du Colombier for(k = 0; k < repl; k++)
653*3e5d0078SDavid du Colombier {
654*3e5d0078SDavid du Colombier tmpface[n] |= (mask-bits) << (k*nbits);
655*3e5d0078SDavid du Colombier tmpmask[n] |= (bits==mask ? 0 : mask) << (k*nbits);
656*3e5d0078SDavid du Colombier }
657*3e5d0078SDavid du Colombier n++;
658*3e5d0078SDavid du Colombier }
659*3e5d0078SDavid du Colombier
660*3e5d0078SDavid du Colombier }
661*3e5d0078SDavid du Colombier
662*3e5d0078SDavid du Colombier if(n != sizeof tmpface) {
663*3e5d0078SDavid du Colombier fprint(2, "can't happen2 --rsc\n");
664*3e5d0078SDavid du Colombier exits("n!=tmpface");
665*3e5d0078SDavid du Colombier }
666*3e5d0078SDavid du Colombier
667*3e5d0078SDavid du Colombier loadimage(im, im->r, tmpface, n);
668*3e5d0078SDavid du Colombier loadimage(imask, imask->r, tmpmask, n);
669*3e5d0078SDavid du Colombier
670*3e5d0078SDavid du Colombier for (i = 0; i < nels(d->faces); i++)
671*3e5d0078SDavid du Colombier {
672*3e5d0078SDavid du Colombier d->faces[i] = eallocimage(display, Rect(0,0,PDUP*NPJW, PDUP*NPJW),
673*3e5d0078SDavid du Colombier screen->chan, 0, DNofill);
674*3e5d0078SDavid du Colombier d->masks[i] = eallocimage(display, Rect(0,0,PDUP*NPJW, PDUP*NPJW),
675*3e5d0078SDavid du Colombier GREY1, 0, DNofill);
676*3e5d0078SDavid du Colombier
677*3e5d0078SDavid du Colombier switch (i) {
678*3e5d0078SDavid du Colombier case 0:
679*3e5d0078SDavid du Colombier copy(d->faces[i], im);
680*3e5d0078SDavid du Colombier copy(d->masks[i], imask);
681*3e5d0078SDavid du Colombier break;
682*3e5d0078SDavid du Colombier
683*3e5d0078SDavid du Colombier case 1:
684*3e5d0078SDavid du Colombier copy(d->faces[i], im);
685*3e5d0078SDavid du Colombier copy(d->masks[i], imask);
686*3e5d0078SDavid du Colombier rotate_clockwise(d->faces[i]);
687*3e5d0078SDavid du Colombier rotate_clockwise(d->masks[i]);
688*3e5d0078SDavid du Colombier break;
689*3e5d0078SDavid du Colombier
690*3e5d0078SDavid du Colombier default:
691*3e5d0078SDavid du Colombier copy(d->faces[i], d->faces[i-2]);
692*3e5d0078SDavid du Colombier copy(d->masks[i], d->masks[i-2]);
693*3e5d0078SDavid du Colombier reflect1_lr(d->faces[i]);
694*3e5d0078SDavid du Colombier reflect1_ud(d->faces[i]);
695*3e5d0078SDavid du Colombier reflect1_lr(d->masks[i]);
696*3e5d0078SDavid du Colombier reflect1_ud(d->masks[i]);
697*3e5d0078SDavid du Colombier break;
698*3e5d0078SDavid du Colombier }
699*3e5d0078SDavid du Colombier }
700*3e5d0078SDavid du Colombier d->face = d->faces[0];
701*3e5d0078SDavid du Colombier d->mask = d->masks[0];
702*3e5d0078SDavid du Colombier
703*3e5d0078SDavid du Colombier d->height = Dy(im->r);
704*3e5d0078SDavid du Colombier d->width = Dx(im->r);
705*3e5d0078SDavid du Colombier
706*3e5d0078SDavid du Colombier d->mass = 1.0;
707*3e5d0078SDavid du Colombier
708*3e5d0078SDavid du Colombier d->spin = nrand(imin(3, total_spin + 1));
709*3e5d0078SDavid du Colombier total_spin -= d->spin;
710*3e5d0078SDavid du Colombier
711*3e5d0078SDavid du Colombier d->pos.x = nrand(screen->r.max.x - d->width);
712*3e5d0078SDavid du Colombier d->pos.y = nrand(screen->r.max.y - d->height);
713*3e5d0078SDavid du Colombier
714*3e5d0078SDavid du Colombier d->vel.x = (double)rrand(-20, 20);
715*3e5d0078SDavid du Colombier d->vel.y = (double)rrand(-20, 20);
716*3e5d0078SDavid du Colombier vtop(&d->ivel, &d->vel);
717*3e5d0078SDavid du Colombier
718*3e5d0078SDavid du Colombier drawdot(d);
719*3e5d0078SDavid du Colombier }
720*3e5d0078SDavid du Colombier
721*3e5d0078SDavid du Colombier int
msec(void)722*3e5d0078SDavid du Colombier msec(void)
723*3e5d0078SDavid du Colombier {
724*3e5d0078SDavid du Colombier static int fd;
725*3e5d0078SDavid du Colombier int n;
726*3e5d0078SDavid du Colombier char buf[64];
727*3e5d0078SDavid du Colombier
728*3e5d0078SDavid du Colombier if(fd <= 0)
729*3e5d0078SDavid du Colombier fd = open("/dev/msec", OREAD);
730*3e5d0078SDavid du Colombier if(fd < 0)
731*3e5d0078SDavid du Colombier return 0;
732*3e5d0078SDavid du Colombier if(seek(fd, 0, 0) < 0)
733*3e5d0078SDavid du Colombier return 0;
734*3e5d0078SDavid du Colombier if((n=read(fd, buf, sizeof(buf)-1)) < 0)
735*3e5d0078SDavid du Colombier return 0;
736*3e5d0078SDavid du Colombier buf[n] = 0;
737*3e5d0078SDavid du Colombier return atoi(buf);
738*3e5d0078SDavid du Colombier }
739*3e5d0078SDavid du Colombier
740*3e5d0078SDavid du Colombier /*
741*3e5d0078SDavid du Colombier * debugging: make del pause so that we can
742*3e5d0078SDavid du Colombier * inspect window.
743*3e5d0078SDavid du Colombier */
744*3e5d0078SDavid du Colombier jmp_buf j;
745*3e5d0078SDavid du Colombier static void
myhandler(void * v,char * s)746*3e5d0078SDavid du Colombier myhandler(void *v, char *s)
747*3e5d0078SDavid du Colombier {
748*3e5d0078SDavid du Colombier if(strcmp(s, "interrupt") == 0)
749*3e5d0078SDavid du Colombier notejmp(v, j, -1);
750*3e5d0078SDavid du Colombier noted(NDFLT);
751*3e5d0078SDavid du Colombier }
752*3e5d0078SDavid du Colombier
753*3e5d0078SDavid du Colombier void
main(int argc,char * argv[])754*3e5d0078SDavid du Colombier main(int argc, char *argv[])
755*3e5d0078SDavid du Colombier {
756*3e5d0078SDavid du Colombier int c;
757*3e5d0078SDavid du Colombier long now, then;
758*3e5d0078SDavid du Colombier
759*3e5d0078SDavid du Colombier ARGBEGIN
760*3e5d0078SDavid du Colombier {
761*3e5d0078SDavid du Colombier case 'i':
762*3e5d0078SDavid du Colombier iflag = 1;
763*3e5d0078SDavid du Colombier gravity = no_gravity;
764*3e5d0078SDavid du Colombier track_length = 64;
765*3e5d0078SDavid du Colombier track_width = 2;
766*3e5d0078SDavid du Colombier break;
767*3e5d0078SDavid du Colombier
768*3e5d0078SDavid du Colombier case 'k':
769*3e5d0078SDavid du Colombier k_floor = atof(ARGF());
770*3e5d0078SDavid du Colombier break;
771*3e5d0078SDavid du Colombier
772*3e5d0078SDavid du Colombier case 'n':
773*3e5d0078SDavid du Colombier track_length = atoi(ARGF());
774*3e5d0078SDavid du Colombier break;
775*3e5d0078SDavid du Colombier
776*3e5d0078SDavid du Colombier case 'w':
777*3e5d0078SDavid du Colombier track_width = atoi(ARGF());
778*3e5d0078SDavid du Colombier break;
779*3e5d0078SDavid du Colombier
780*3e5d0078SDavid du Colombier case 'x':
781*3e5d0078SDavid du Colombier gravity.x = atof(ARGF());
782*3e5d0078SDavid du Colombier break;
783*3e5d0078SDavid du Colombier
784*3e5d0078SDavid du Colombier case 'y':
785*3e5d0078SDavid du Colombier gravity.y = atof(ARGF());
786*3e5d0078SDavid du Colombier break;
787*3e5d0078SDavid du Colombier
788*3e5d0078SDavid du Colombier default:
789*3e5d0078SDavid du Colombier fprint(2, "Usage: %s [-i] [-k k_floor] [-n track_length] [-w track_width] [-x gravityx] [-y gravityy]\n", argv0);
790*3e5d0078SDavid du Colombier exits("usage");
791*3e5d0078SDavid du Colombier } ARGEND
792*3e5d0078SDavid du Colombier
793*3e5d0078SDavid du Colombier if (track_length > MAXTRACKS)
794*3e5d0078SDavid du Colombier track_length = MAXTRACKS;
795*3e5d0078SDavid du Colombier
796*3e5d0078SDavid du Colombier if (track_length == 0)
797*3e5d0078SDavid du Colombier track_width = 0;
798*3e5d0078SDavid du Colombier
799*3e5d0078SDavid du Colombier srand(time(0));
800*3e5d0078SDavid du Colombier
801*3e5d0078SDavid du Colombier initdraw(0,0,0);
802*3e5d0078SDavid du Colombier im = eallocimage(display, Rect(0, 0, PDUP*NPJW, PDUP*NPJW), CMAP8, 0, DNofill);
803*3e5d0078SDavid du Colombier
804*3e5d0078SDavid du Colombier draw(screen, screen->r, display->black, nil, ZP);
805*3e5d0078SDavid du Colombier
806*3e5d0078SDavid du Colombier /* track = balloc(Rect(0, 0, track_width, track_width), 0); */
807*3e5d0078SDavid du Colombier
808*3e5d0078SDavid du Colombier edot = &dot[0];
809*3e5d0078SDavid du Colombier
810*3e5d0078SDavid du Colombier setup(edot++, "andrew", andrewbits, nels(andrewbits));
811*3e5d0078SDavid du Colombier setup(edot++, "bart", bartbits, nels(bartbits));
812*3e5d0078SDavid du Colombier setup(edot++, "bwk", bwkbits, nels(bwkbits));
813*3e5d0078SDavid du Colombier setup(edot++, "dmr", dmrbits, nels(dmrbits));
814*3e5d0078SDavid du Colombier setup(edot++, "doug", dougbits, nels(dougbits));
815*3e5d0078SDavid du Colombier setup(edot++, "gerard", gerardbits, nels(gerardbits));
816*3e5d0078SDavid du Colombier setup(edot++, "howard", howardbits, nels(howardbits));
817*3e5d0078SDavid du Colombier setup(edot++, "ken", kenbits, nels(kenbits));
818*3e5d0078SDavid du Colombier setup(edot++, "philw", philwbits, nels(philwbits));
819*3e5d0078SDavid du Colombier setup(edot++, "pjw", pjwbits, nels(pjwbits));
820*3e5d0078SDavid du Colombier setup(edot++, "presotto", presottobits, nels(presottobits));
821*3e5d0078SDavid du Colombier setup(edot++, "rob", robbits, nels(robbits));
822*3e5d0078SDavid du Colombier setup(edot++, "sean", seanbits, nels(seanbits));
823*3e5d0078SDavid du Colombier setup(edot++, "td", tdbits, nels(tdbits));
824*3e5d0078SDavid du Colombier
825*3e5d0078SDavid du Colombier if(PDUP > 1) { /* assume debugging */
826*3e5d0078SDavid du Colombier setjmp(j);
827*3e5d0078SDavid du Colombier read(0, &c, 1);
828*3e5d0078SDavid du Colombier
829*3e5d0078SDavid du Colombier /* make DEL pause so that we can inspect window */
830*3e5d0078SDavid du Colombier notify(myhandler);
831*3e5d0078SDavid du Colombier }
832*3e5d0078SDavid du Colombier SET(c);
833*3e5d0078SDavid du Colombier USED(c);
834*3e5d0078SDavid du Colombier
835*3e5d0078SDavid du Colombier #define DELAY 100
836*3e5d0078SDavid du Colombier for (then = msec();; then = msec())
837*3e5d0078SDavid du Colombier {
838*3e5d0078SDavid du Colombier Dot *d;
839*3e5d0078SDavid du Colombier
840*3e5d0078SDavid du Colombier for (d = dot; d != edot; d++)
841*3e5d0078SDavid du Colombier undraw(d);
842*3e5d0078SDavid du Colombier for (d = dot; d != edot; d++)
843*3e5d0078SDavid du Colombier upd(d);
844*3e5d0078SDavid du Colombier draw(screen, screen->r, screen, nil, screen->r.min);
845*3e5d0078SDavid du Colombier flushimage(display, 1);
846*3e5d0078SDavid du Colombier now = msec();
847*3e5d0078SDavid du Colombier if(now - then < DELAY)
848*3e5d0078SDavid du Colombier sleep(DELAY - (now - then));
849*3e5d0078SDavid du Colombier }
850*3e5d0078SDavid du Colombier }
851