Update Math-BigInt-FastCalc Perl distribution to 0.5018 for Perl 5.36 and 5.38
[oi-userland.git] / components / x11 / xlock / src / pyro.c
blob1886e171116afb6b3dd7097607521ec1af4edea2
1 /*
2 * Copyright (c) 1988-91 by Patrick J. Naughton.
4 * Permission to use, copy, modify, and distribute this software and its
5 * documentation for any purpose and without fee is hereby granted,
6 * provided that the above copyright notice appear in all copies and that
7 * both that copyright notice and this permission notice appear in
8 * supporting documentation.
10 * This file is provided AS IS with no warranties of any kind. The author
11 * shall have no liability with respect to the infringement of copyrights,
12 * trade secrets or any patents by this file or any part thereof. In no
13 * event will the author be liable for any lost revenue or profits or
14 * other special, indirect and consequential damages.
18 * Copyright (c) 1991, 2015, Oracle and/or its affiliates. All rights reserved.
20 * Permission is hereby granted, free of charge, to any person obtaining a
21 * copy of this software and associated documentation files (the "Software"),
22 * to deal in the Software without restriction, including without limitation
23 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
24 * and/or sell copies of the Software, and to permit persons to whom the
25 * Software is furnished to do so, subject to the following conditions:
27 * The above copyright notice and this permission notice (including the next
28 * paragraph) shall be included in all copies or substantial portions of the
29 * Software.
31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
34 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
36 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
37 * DEALINGS IN THE SOFTWARE.
39 /*-
40 * pyro.c - Fireworks for xlock, the X Window System lockscreen.
42 * Copyright (c) 1991 by Patrick J. Naughton.
44 * See xlock.c for copying information.
46 * Revision History:
47 * 16-Mar-91: Written. (received from David Brooks, brooks@osf.org).
50 /* The physics of the rockets is a little bogus, but it looks OK. Each is
51 * given an initial velocity impetus. They decelerate slightly (gravity
52 * overcomes the rocket's impulse) and explode as the rocket's main fuse
53 * gives out (we could add a ballistic stage, maybe). The individual
54 * stars fan out from the rocket, and they decelerate less quickly.
55 * That's called bouyancy, but really it's again a visual preference.
58 #include "xlock.h"
59 #include <math.h>
60 #define TWOPI 6.2831853
62 /* Define this >1 to get small rectangles instead of points */
63 #ifndef STARSIZE
64 #define STARSIZE 1
65 #endif
67 #define SILENT 0
68 #define REDGLARE 1
69 #define BURSTINGINAIR 2
71 #define CLOUD 0
72 #define DOUBLECLOUD 1
73 /* Clearly other types and other fascinating visual effects could be added...*/
75 /* P_xxx parameters represent the reciprocal of the probability... */
76 #define P_IGNITE 5000 /* ...of ignition per cycle */
77 #define P_DOUBLECLOUD 10 /* ...of an ignition being double */
78 #define P_MULTI 75 /* ...of an ignition being several @ once */
79 #define P_FUSILLADE 250 /* ...of an ignition starting a fusillade */
81 #define ROCKETW 2 /* Dimensions of rocket */
82 #define ROCKETH 4
83 #define XVELFACTOR 0.0025 /* Max horizontal velocity / screen width */
84 #define MINYVELFACTOR 0.016 /* Min vertical velocity / screen height */
85 #define MAXYVELFACTOR 0.018
86 #define GRAVFACTOR 0.0002 /* delta v / screen height */
87 #define MINFUSE 50 /* range of fuse lengths for rocket */
88 #define MAXFUSE 100
90 #define FUSILFACTOR 10 /* Generate fusillade by reducing P_IGNITE */
91 #define FUSILLEN 100 /* Length of fusillade, in ignitions */
93 #define SVELFACTOR 0.1 /* Max star velocity / yvel */
94 #define BOUYANCY 0.2 /* Reduction in grav deceleration for stars */
95 #define MAXSTARS 75 /* Number of stars issued from a shell */
96 #define MINSTARS 50
97 #define MINSFUSE 50 /* Range of fuse lengths for stars */
98 #define MAXSFUSE 100
100 #define INTRAND(min,max) ((int) (random()%((max+1)-(min))+(min)))
101 #define FLOATRAND(min,max) ((min)+(random()/MAXRAND)*((max)-(min)))
103 typedef struct {
104 int state;
105 int shelltype;
106 unsigned long color1, color2;
107 int fuse;
108 float xvel, yvel;
109 float x, y;
110 int nstars;
111 #if STARSIZE > 1
112 XRectangle Xpoints[MAXSTARS];
113 XRectangle Xpoints2[MAXSTARS];
114 #else
115 XPoint Xpoints[MAXSTARS];
116 XPoint Xpoints2[MAXSTARS];
117 #endif
118 float sx[MAXSTARS], sy[MAXSTARS]; /* Distance from notional
119 * center */
120 float sxvel[MAXSTARS], syvel[MAXSTARS]; /* Relative to notional
121 * center */
122 } rocket;
124 typedef struct {
125 Screen *scr;
126 Colormap cmap;
127 int p_ignite;
128 unsigned long bgpixel;
129 unsigned long fgpixel;
130 unsigned long rockpixel;
131 GC bgGC;
132 int nflying;
133 int fusilcount;
134 int width, lmargin, rmargin, height;
135 float minvelx, maxvelx;
136 float minvely, maxvely;
137 float maxsvel;
138 float rockdecel, stardecel;
139 rocket *rockq;
140 } pyrostruct;
142 static pyrostruct pyros[MAXSCREENS];
143 static int orig_p_ignite;
144 static int just_started = True;/* Greet the user right away */
146 static void ignite(pyrostruct *pp);
147 static void animate(Window win, pyrostruct *pp, rocket *rp);
148 static void shootup(Window win, pyrostruct *pp, rocket *rp);
149 static void burst(Window win, pyrostruct *pp, rocket *rp);
151 void
152 initpyro(Window win)
154 pyrostruct *pp = &pyros[screen];
155 rocket *rp;
156 XWindowAttributes xwa;
157 XGCValues xgcv;
158 unsigned int rockn;
159 #if STARSIZE > 1
160 unsigned int starn;
161 short bsize;
162 #endif
164 XGetWindowAttributes(dsp, win, &xwa);
166 if ((batchcount < 1) || (batchcount > 1024))
167 batchcount = 40;
169 orig_p_ignite = P_IGNITE / batchcount;
170 if (orig_p_ignite <= 0)
171 orig_p_ignite = 1;
172 pp->p_ignite = orig_p_ignite;
174 if (pp->rockq == NULL) {
175 pp->rockq = calloc(batchcount, sizeof(rocket));
176 if (pp->rockq == NULL)
177 error("allocation failed, unable to launch rockets\n");
179 pp->nflying = pp->fusilcount = 0;
181 #if STARSIZE > 1
182 bsize = (short) ((xwa.height <= 64) ? 1 : STARSIZE);
183 #endif
184 for (rockn = 0, rp = pp->rockq; rockn < batchcount; rockn++, rp++) {
185 rp->state = SILENT;
186 #if STARSIZE > 1
187 for (starn = 0; starn < MAXSTARS; starn++) {
188 rp->Xpoints[starn].width = rp->Xpoints[starn].height =
189 rp->Xpoints2[starn].width = rp->Xpoints2[starn].height = bsize;
191 #endif
194 pp->width = xwa.width;
195 pp->lmargin = xwa.width / 16;
196 pp->rmargin = xwa.width - pp->lmargin;
197 pp->height = xwa.height;
198 pp->scr = ScreenOfDisplay(dsp, screen);
199 pp->cmap = xwa.colormap;
201 pp->fgpixel = sswhite[screen].pixel;
202 pp->bgpixel = ssblack[screen].pixel;
203 if (!mono && Scr[screen].npixels > 3)
204 pp->rockpixel = Scr[screen].pixels[3]; /* Just the right shade of
205 * orange */
206 else
207 pp->rockpixel = pp->fgpixel;
209 if (!pp->bgGC) {
210 xgcv.foreground = pp->bgpixel;
211 pp->bgGC = XCreateGC(dsp, win, GCForeground, &xgcv);
213 /* Geometry-dependent physical data: */
214 pp->maxvelx = (float) (xwa.width) * XVELFACTOR;
215 pp->minvelx = -pp->maxvelx;
216 pp->minvely = -(float) (xwa.height) * MINYVELFACTOR;
217 pp->maxvely = -(float) (xwa.height) * MAXYVELFACTOR;
218 pp->maxsvel = pp->minvely * SVELFACTOR;
219 pp->rockdecel = (float) (pp->height) * GRAVFACTOR;
220 pp->stardecel = pp->rockdecel * BOUYANCY;
222 XFillRectangle(dsp, win, pp->bgGC, 0, 0, xwa.width, xwa.height);
225 void
226 drawpyro(Window win)
228 pyrostruct *pp = &pyros[screen];
229 rocket *rp;
230 int rockn;
232 if (pp->p_ignite == 0)
233 pp->p_ignite = 1;
234 if (just_started || (random() % pp->p_ignite == 0)) {
235 just_started = False;
236 if (random() % P_FUSILLADE == 0) {
237 pp->p_ignite = orig_p_ignite / FUSILFACTOR;
238 pp->fusilcount = INTRAND(FUSILLEN * 9 / 10, FUSILLEN * 11 / 10);
240 ignite(pp);
241 if (pp->fusilcount > 0) {
242 if (--pp->fusilcount == 0)
243 pp->p_ignite = orig_p_ignite;
246 for (rockn = pp->nflying, rp = pp->rockq; rockn > 0; rp++) {
247 if (rp->state != SILENT) {
248 animate(win, pp, rp);
249 rockn--;
254 static void
255 ignite(pyrostruct *pp)
257 rocket *rp;
258 int multi, shelltype, nstars, fuse, npix, pix;
259 unsigned long color1, color2;
260 float xvel, yvel, x;
262 x = random() % pp->width;
263 xvel = FLOATRAND(-pp->maxvelx, pp->maxvelx);
264 /* All this to stop too many rockets going offscreen: */
265 if (x < pp->lmargin && xvel < 0.0 || x > pp->rmargin && xvel > 0.0)
266 xvel = -xvel;
267 yvel = FLOATRAND(pp->minvely, pp->maxvely);
268 fuse = INTRAND(MINFUSE, MAXFUSE);
269 nstars = INTRAND(MINSTARS, MAXSTARS);
270 if (!mono && (npix = Scr[screen].npixels) > 2) {
271 color1 = Scr[screen].pixels[pix = (int) random() % npix];
272 color2 = Scr[screen].pixels[(pix + (npix / 2)) % npix];
273 } else {
274 color1 = color2 = sswhite[screen].pixel;
277 multi = 1;
278 if (random() % P_DOUBLECLOUD == 0)
279 shelltype = DOUBLECLOUD;
280 else {
281 shelltype = CLOUD;
282 if (random() % P_MULTI == 0)
283 multi = INTRAND(5, 15);
286 rp = pp->rockq;
287 while (multi--) {
288 if (pp->nflying >= batchcount)
289 return;
290 while (rp->state != SILENT)
291 rp++;
292 pp->nflying++;
293 rp->shelltype = shelltype;
294 rp->state = REDGLARE;
295 rp->color1 = color1;
296 rp->color2 = color2;
297 rp->xvel = xvel;
298 rp->yvel = FLOATRAND(yvel * 0.97, yvel * 1.03);
299 rp->fuse = INTRAND((fuse * 90) / 100, (fuse * 110) / 100);
300 rp->x = x + FLOATRAND(multi * 7.6, multi * 8.4);
301 rp->y = pp->height - 1;
302 rp->nstars = nstars;
306 static void
307 animate(
308 Window win,
309 pyrostruct *pp,
310 rocket *rp
313 int starn;
314 float r, theta;
316 if (rp->state == REDGLARE) {
317 shootup(win, pp, rp);
319 /* Handle setup for explosion */
320 if (rp->state == BURSTINGINAIR) {
321 for (starn = 0; starn < rp->nstars; starn++) {
322 rp->sx[starn] = rp->sy[starn] = 0.0;
323 rp->Xpoints[starn].x = (short) rp->x;
324 rp->Xpoints[starn].y = (short) rp->y;
325 if (rp->shelltype == DOUBLECLOUD) {
326 rp->Xpoints2[starn].x = (short) rp->x;
327 rp->Xpoints2[starn].y = (short) rp->y;
329 /* This isn't accurate solid geometry, but it looks OK. */
331 r = FLOATRAND(0.0, pp->maxsvel);
332 theta = FLOATRAND(0.0, TWOPI);
333 rp->sxvel[starn] = r * cos(theta);
334 rp->syvel[starn] = r * sin(theta);
336 rp->fuse = INTRAND(MINSFUSE, MAXSFUSE);
339 if (rp->state == BURSTINGINAIR) {
340 burst(win, pp, rp);
344 static void
345 shootup(
346 Window win,
347 pyrostruct *pp,
348 rocket *rp
351 XFillRectangle(dsp, win, pp->bgGC, (int) (rp->x), (int) (rp->y),
352 ROCKETW, ROCKETH + 3);
354 if (rp->fuse-- <= 0) {
355 rp->state = BURSTINGINAIR;
356 return;
358 rp->x += rp->xvel;
359 rp->y += rp->yvel;
360 rp->yvel += pp->rockdecel;
361 XSetForeground(dsp, Scr[screen].gc, pp->rockpixel);
362 XFillRectangle(dsp, win, Scr[screen].gc, (int) (rp->x), (int) (rp->y),
363 ROCKETW, (int) (ROCKETH + random() % 4));
366 static void
367 burst(
368 Window win,
369 pyrostruct *pp,
370 rocket *rp
373 register int starn;
374 register int nstars, stype;
375 register float rx, ry, sd; /* Help compiler optimize :-) */
376 register float sx, sy;
378 nstars = rp->nstars;
379 stype = rp->shelltype;
381 #if STARSIZE > 1
382 XFillRectangles(dsp, win, pp->bgGC, rp->Xpoints, nstars);
383 if (stype == DOUBLECLOUD)
384 XFillRectangles(dsp, win, pp->bgGC, rp->Xpoints2, nstars);
385 #else
386 XDrawPoints(dsp, win, pp->bgGC, rp->Xpoints, nstars, CoordModeOrigin);
387 if (stype == DOUBLECLOUD)
388 XDrawPoints(dsp, win, pp->bgGC, rp->Xpoints2, nstars, CoordModeOrigin);
389 #endif
391 if (rp->fuse-- <= 0) {
392 rp->state = SILENT;
393 pp->nflying--;
394 return;
396 /* Stagger the stars' decay */
397 if (rp->fuse <= 7) {
398 if ((rp->nstars = nstars = nstars * 90 / 100) == 0)
399 return;
401 rx = rp->x;
402 ry = rp->y;
403 sd = pp->stardecel;
404 for (starn = 0; starn < nstars; starn++) {
405 sx = rp->sx[starn] += rp->sxvel[starn];
406 sy = rp->sy[starn] += rp->syvel[starn];
407 rp->syvel[starn] += sd;
408 rp->Xpoints[starn].x = (short) (rx + sx);
409 rp->Xpoints[starn].y = (short) (ry + sy);
410 if (stype == DOUBLECLOUD) {
411 rp->Xpoints2[starn].x = (short) (rx + 1.7 * sx);
412 rp->Xpoints2[starn].y = (short) (ry + 1.7 * sy);
415 rp->x = rx + rp->xvel;
416 rp->y = ry + rp->yvel;
417 rp->yvel += sd;
419 XSetForeground(dsp, Scr[screen].gc, rp->color1);
420 #if STARSIZE > 1
421 XFillRectangles(dsp, win, Scr[screen].gc, rp->Xpoints, nstars);
422 if (stype == DOUBLECLOUD) {
423 XSetForeground(dsp, Scr[screen].gc, rp->color2);
424 XFillRectangles(dsp, win, Scr[screen].gc, rp->Xpoints2, nstars);
426 #else
427 XDrawPoints(dsp, win, Scr[screen].gc, rp->Xpoints, nstars, CoordModeOrigin);
428 if (stype == DOUBLECLOUD) {
429 XSetForeground(dsp, Scr[screen].gc, rp->color2);
430 XDrawPoints(dsp, win, Scr[screen].gc, rp->Xpoints2, nstars,
431 CoordModeOrigin);
433 #endif