~ubuntu-branches/ubuntu/lucid/xscreensaver/lucid

« back to all changes in this revision

Viewing changes to hacks/penetrate.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2007-12-06 09:53:12 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20071206095312-fkzcwe4vqm50z208
Tags: 5.04-1ubuntu1
* Merge from debian unstable, remaining changes:
  - split xscreensaver into xscreensaver, xscreensaver-data (hacks we ship),
    xscreensaver-data-extra (hacks in universe). split out gl hacks for
    universe to xscreensaver-gl-extra
  - use fridge for rss screensavers
  - create and install .desktop files for gnome-screensaver

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 1999
2
 
 *  Adam Miller adum@aya.yale.edu
 
1
/* Copyright (c) 1999 Adam Miller adum@aya.yale.edu
3
2
 *
4
3
 * Permission to use, copy, modify, distribute, and sell this software and its
5
4
 * documentation for any purpose is hereby granted without fee, provided that
31
30
#define kSleepTime 10000 
32
31
 
33
32
#define font_height(font)               (font->ascent + font->descent)
34
 
#define FONT_NAME                       "-*-times-*-*-*-*-80-*-*-*-*-*-*-*"
35
33
 
36
34
#define kCityPause 500000
37
35
#define kLevelPause 1
40
38
#define kMinRate 30
41
39
#define kMaxRadius 100
42
40
 
43
 
static XFontStruct *font, *scoreFont;
44
 
static GC draw_gc, erase_gc, level_gc;
45
 
static unsigned int default_fg_pixel;
46
 
static XColor scoreColor;
47
 
 
48
 
int bgrowth;
49
 
int lrate = 80, startlrate;
50
 
long loop = 0;
51
 
long score = 0, highscore = 0;
52
 
long nextBonus = kFirstBonus;
53
 
int numBonus = 0;
54
 
int bround = 0;
55
 
long lastLaser = 0;
56
 
int gamez = 0;
57
 
int aim = 180;
58
 
int econpersen = 0;
59
 
int choosypersen = 0;
60
 
int carefulpersen = 0;
61
 
int smart = 0;
62
 
 
63
41
typedef struct {
64
42
  int alive;
65
43
  int x, y;
110
88
#define kMissileSpeed 0.003
111
89
#define kLaserSpeed (kMissileSpeed * 6)
112
90
 
113
 
Missile missile[kMaxMissiles];
114
 
Boom boom[kMaxBooms];
115
 
City city[kNumCities];
116
 
Laser laser[kMaxLasers];
117
 
int blive[kNumCities];
118
 
 
119
 
static void Explode(int x, int y, int max, XColor color, int oflaser)
 
91
 
 
92
struct state {
 
93
  Display *dpy;
 
94
  Window window;
 
95
 
 
96
   XFontStruct *font, *scoreFont;
 
97
   GC draw_gc, erase_gc, level_gc;
 
98
   unsigned int default_fg_pixel;
 
99
   XColor scoreColor;
 
100
 
 
101
   int bgrowth;
 
102
   int lrate, startlrate;
 
103
   long loop;
 
104
   long score, highscore;
 
105
   long nextBonus;
 
106
   int numBonus;
 
107
   int bround;
 
108
   long lastLaser;
 
109
   int gamez;
 
110
   int aim;
 
111
   int econpersen;
 
112
   int choosypersen;
 
113
   int carefulpersen;
 
114
   int smart;
 
115
   Colormap cmap;
 
116
 
 
117
   Missile missile[kMaxMissiles];
 
118
   Boom boom[kMaxBooms];
 
119
   City city[kNumCities];
 
120
   Laser laser[kMaxLasers];
 
121
   int blive[kNumCities];
 
122
 
 
123
   int level, levMissiles, levFreq;
 
124
 
 
125
   int draw_xlim, draw_ylim;
 
126
   int draw_reset;
 
127
};
 
128
 
 
129
 
 
130
static void Explode(struct state *st, int x, int y, int max, XColor color, int oflaser)
120
131
{
121
132
  int i;
122
133
  Boom *m = 0;
123
134
  for (i=0;i<kMaxBooms;i++)
124
 
         if (!boom[i].alive) {
125
 
                m = &boom[i];
 
135
         if (!st->boom[i].alive) {
 
136
                m = &st->boom[i];
126
137
                break;
127
138
         }
128
139
  if (!m)
140
151
  m->oflaser = oflaser;
141
152
}
142
153
 
143
 
static void launch (int xlim, int ylim,
144
 
        Display *dpy, Colormap cmap, int src)
 
154
static void launch (struct state *st, int xlim, int ylim, int src)
145
155
{
146
156
  int i;
147
157
  Missile *m = 0, *msrc;
148
158
  for (i=0;i<kMaxMissiles;i++)
149
 
         if (!missile[i].alive) {
150
 
                m = &missile[i];
 
159
         if (!st->missile[i].alive) {
 
160
                m = &st->missile[i];
151
161
                break;
152
162
         }
153
163
  if (!m)
161
171
  m->jenis = random() % 360;
162
172
  m->splits = 0;
163
173
  if (m->jenis < 50) {
164
 
         m->splits = random() % ((int) (ylim * 0.4));
 
174
    int j = ylim * 0.4;
 
175
    if (j)
 
176
         m->splits = random() % j;
165
177
         if (m->splits < ylim * 0.08)
166
178
                m->splits = 0;
167
179
  }
169
181
  /* special if we're from another missile */
170
182
  if (src >= 0) {
171
183
         int dc = random() % (kNumCities - 1);
172
 
         msrc = &missile[src];
 
184
         msrc = &st->missile[src];
173
185
         if (dc == msrc->dcity)
174
186
                dc++;
175
187
         m->dcity = dc;
181
193
  }
182
194
  else
183
195
         m->dcity = random() % kNumCities;
184
 
  m->endx = city[m->dcity].x + (random() % 20) - 10;
 
196
  m->endx = st->city[m->dcity].x + (random() % 20) - 10;
185
197
  m->x = m->startx;
186
198
  m->y = m->starty;
187
199
  m->enemies = 0;
190
202
         hsv_to_rgb (m->jenis, 1.0, 1.0,
191
203
                                         &m->color.red, &m->color.green, &m->color.blue);
192
204
         m->color.flags = DoRed | DoGreen | DoBlue;
193
 
         if (!XAllocColor (dpy, cmap, &m->color)) {
194
 
                m->color.pixel = WhitePixel (dpy, DefaultScreen (dpy));
 
205
         if (!XAllocColor (st->dpy, st->cmap, &m->color)) {
 
206
                m->color.pixel = WhitePixel (st->dpy, DefaultScreen (st->dpy));
195
207
                m->color.red = m->color.green = m->color.blue = 0xFFFF;
196
208
         }
197
209
  }
200
212
#define kExpHelp 0.2
201
213
#define kSpeedDiff 3.5
202
214
#define kMaxToGround 0.75
203
 
static int fire(int xlim, int ylim,
204
 
        Display *dpy, Window window, Colormap cmap)
 
215
static int fire(struct state *st, int xlim, int ylim)
205
216
{
206
217
  int i, j, cnt = 0;
207
218
  int dcity;
216
227
  int deepest = 0;
217
228
  int misnum = 0;
218
229
 
219
 
  choosy = (random() % 100) < choosypersen;
220
 
  economic = (random() % 100) < econpersen;
221
 
  careful = (random() % 100) < carefulpersen;
 
230
  choosy = (random() % 100) < st->choosypersen;
 
231
  economic = (random() % 100) < st->econpersen;
 
232
  careful = (random() % 100) < st->carefulpersen;
222
233
 
223
234
  /* count our cities */
224
235
  for (i=0;i<kNumCities;i++)
225
 
         livecity += city[i].alive;
 
236
         livecity += st->city[i].alive;
226
237
  if (livecity == 0)
227
238
         return 1;  /* no guns */
228
239
 
229
240
  for (i=0;i<kMaxLasers;i++)
230
 
         if (!laser[i].alive) {
231
 
                m = &laser[i];
 
241
         if (!st->laser[i].alive) {
 
242
                m = &st->laser[i];
232
243
                break;
233
244
         }
234
245
  if (!m)
238
249
  if (choosy) {
239
250
         int choo = 0;
240
251
         for (j=0;j<kMaxMissiles;j++) {
241
 
                mis = &missile[j];
 
252
                mis = &st->missile[j];
242
253
                if (!mis->alive || (mis->y > ytargetmin))
243
254
                  continue;
244
 
                if (city[mis->dcity].alive)
 
255
                if (st->city[mis->dcity].alive)
245
256
                  choo++;
246
257
         }
247
258
         if (choo == 0)
249
260
  }
250
261
 
251
262
  for (j=0;j<kMaxMissiles;j++) {
252
 
         mis = &missile[j];
 
263
         mis = &st->missile[j];
253
264
         suitor[j] = 0;
254
265
         if (!mis->alive || (mis->y > ytargetmin))
255
266
                continue;
256
 
         if (choosy && (city[mis->dcity].alive == 0))
 
267
         if (choosy && (st->city[mis->dcity].alive == 0))
257
268
                continue;
258
269
         ey = mis->starty + ((float) (mis->endy - mis->starty)) * (mis->pos + kExpHelp + (1.0 - mis->pos) / kSpeedDiff);
259
270
         if (ey > ylim * kMaxToGround)
265
276
  /* count missiles that are on target and not being targeted */
266
277
  if (choosy && economic)
267
278
         for (j=0;j<kMaxMissiles;j++)
268
 
                if (suitor[j] && missile[j].enemies == 0)
 
279
                if (suitor[j] && st->missile[j].enemies == 0)
269
280
                  untargeted++;
270
281
 
271
282
  if (economic)
272
283
         for (j=0;j<kMaxMissiles;j++) {
273
284
                if (suitor[j] && cnt > 1)
274
 
                  if (missile[j].enemies > 0)
275
 
                         if (missile[j].enemies > 1 || untargeted == 0) {
 
285
                  if (st->missile[j].enemies > 0)
 
286
                         if (st->missile[j].enemies > 1 || untargeted == 0) {
276
287
                                suitor[j] = 0;
277
288
                                cnt--;
278
289
                         }
279
290
                /* who's closest? biggest threat */
280
 
                if (suitor[j] && missile[j].y > deepest)
281
 
                  deepest = missile[j].y;
 
291
                if (suitor[j] && st->missile[j].y > deepest)
 
292
                  deepest = st->missile[j].y;
282
293
         }
283
294
 
284
295
  if (deepest > 0 && careful) {
285
296
         /* only target deepest missile */
286
297
         cnt = 1;
287
298
         for (j=0;j<kMaxMissiles;j++)
288
 
                if (suitor[j] && missile[j].y != deepest)
 
299
                if (suitor[j] && st->missile[j].y != deepest)
289
300
                  suitor[j] = 0;
290
301
  }
291
302
 
295
306
  for (j=0;j<kMaxMissiles;j++)
296
307
         if (suitor[j])
297
308
                if (cnt-- == 0) {
298
 
                  mis = &missile[j];
 
309
                  mis = &st->missile[j];
299
310
                  misnum = j;
300
311
                  break;
301
312
                }
305
316
 
306
317
  dcity = random() % livecity;
307
318
  for (j=0;j<kNumCities;j++)
308
 
         if (city[j].alive)
 
319
         if (st->city[j].alive)
309
320
                if (dcity-- == 0) {
310
321
                  dcity = j;
311
322
                  break;
312
323
                }
313
 
  m->startx = city[dcity].x;
 
324
  m->startx = st->city[dcity].x;
314
325
  m->starty = ylim;
315
326
  ex = mis->startx + ((float) (mis->endx - mis->startx)) * (mis->pos + kExpHelp + (1.0 - mis->pos) / kSpeedDiff);
316
327
  ey = mis->starty + ((float) (mis->endy - mis->starty)) * (mis->pos + kExpHelp + (1.0 - mis->pos) / kSpeedDiff);
317
 
  m->endx = ex + random() % 16 - 8 + (random() % aim) - aim / 2;
318
 
  m->endy = ey + random() % 16 - 8 + (random() % aim) - aim / 2;
 
328
  m->endx = ex + random() % 16 - 8 + (random() % st->aim) - st->aim / 2;
 
329
  m->endy = ey + random() % 16 - 8 + (random() % st->aim) - st->aim / 2;
319
330
  if (ey > ylim * kMaxToGround)
320
331
         return 0;  /* too far down */
321
332
  mis->enemies++;
341
352
         m->color.green = 0xFFFF;
342
353
         m->color.red = 0xFFFF;
343
354
         m->color.flags = DoRed | DoGreen | DoBlue;
344
 
         if (!XAllocColor (dpy, cmap, &m->color)) {
345
 
                m->color.pixel = WhitePixel (dpy, DefaultScreen (dpy));
 
355
         if (!XAllocColor (st->dpy, st->cmap, &m->color)) {
 
356
                m->color.pixel = WhitePixel (st->dpy, DefaultScreen (st->dpy));
346
357
                m->color.red = m->color.green = m->color.blue = 0xFFFF;
347
358
         }
348
359
  }
349
360
  return 1;
350
361
}
351
362
 
352
 
static Colormap
353
 
init_penetrate(Display *dpy, Window window)
 
363
static void *
 
364
penetrate_init (Display *dpy, Window window)
354
365
{
 
366
  struct state *st = (struct state *) calloc (1, sizeof(*st));
355
367
  int i;
356
368
  /*char *fontname =   "-*-new century schoolbook-*-r-*-*-*-380-*-*-*-*-*-*"; */
357
369
  char *fontname =   "-*-courier-*-r-*-*-*-380-*-*-*-*-*-*";
358
 
  char **list;
359
 
  int foo;
360
 
  Colormap cmap;
361
370
  XGCValues gcv;
362
371
  XWindowAttributes xgwa;
363
 
  XGetWindowAttributes (dpy, window, &xgwa);
364
 
  cmap = xgwa.colormap;
365
 
 
366
 
  if (get_string_resource("smart","String")!=NULL && get_string_resource("smart","String")[0]!=0)
367
 
         smart = 1;
368
 
  bgrowth = get_integer_resource ("bgrowth", "Integer");
369
 
  lrate = get_integer_resource ("lrate", "Integer");
370
 
  if (bgrowth < 0) bgrowth = 2;
371
 
  if (lrate < 0) lrate = 2;
372
 
  startlrate = lrate;
373
 
 
374
 
  if (!fontname || !(font = XLoadQueryFont(dpy, fontname))) {
375
 
         list = XListFonts(dpy, FONT_NAME, 32767, &foo);
376
 
         for (i = 0; i < foo; i++)
377
 
                if ((font = XLoadQueryFont(dpy, list[i])))
378
 
                  break;
379
 
         if (!font) {
380
 
                fprintf (stderr, "%s: Can't find a large font.", progname);
381
 
            exit (1);
382
 
         }
383
 
         XFreeFontNames(list);
384
 
  }
385
 
 
386
 
  if (!(scoreFont = XLoadQueryFont(dpy, "-*-times-*-r-*-*-*-180-*-*-*-*-*-*")))
 
372
 
 
373
  st->dpy = dpy;
 
374
  st->window = window;
 
375
 
 
376
  XGetWindowAttributes (st->dpy, st->window, &xgwa);
 
377
  st->cmap = xgwa.colormap;
 
378
 
 
379
  st->lrate = 80;
 
380
  st->nextBonus = kFirstBonus;
 
381
  st->aim = 180;
 
382
 
 
383
  st->smart = get_boolean_resource(st->dpy, "smart","Boolean");
 
384
  st->bgrowth = get_integer_resource (st->dpy, "bgrowth", "Integer");
 
385
  st->lrate = get_integer_resource (st->dpy, "lrate", "Integer");
 
386
  if (st->bgrowth < 0) st->bgrowth = 2;
 
387
  if (st->lrate < 0) st->lrate = 2;
 
388
  st->startlrate = st->lrate;
 
389
 
 
390
  if (!fontname || !*fontname)
 
391
    fprintf (stderr, "%s: no font specified.\n", progname);
 
392
  st->font = XLoadQueryFont(st->dpy, fontname);
 
393
  if (!st->font)
 
394
    fprintf (stderr, "%s: could not load font %s.\n", progname, fontname);
 
395
 
 
396
  if (!(st->scoreFont = XLoadQueryFont(st->dpy, "-*-times-*-r-*-*-*-180-*-*-*-*-*-*")))
387
397
         fprintf(stderr, "%s: Can't load Times font.", progname);
388
398
 
389
399
  for (i = 0; i < kMaxMissiles; i++)
390
 
    missile[i].alive = 0;
 
400
    st->missile[i].alive = 0;
391
401
 
392
402
  for (i = 0; i < kMaxLasers; i++)
393
 
    laser[i].alive = 0;
 
403
    st->laser[i].alive = 0;
394
404
 
395
405
  for (i = 0; i < kMaxBooms; i++)
396
 
    boom[i].alive = 0;
 
406
    st->boom[i].alive = 0;
397
407
 
398
408
  for (i = 0; i < kNumCities; i++) {
399
 
         City *m = &city[i];
 
409
         City *m = &st->city[i];
400
410
    m->alive = 1;
401
411
         m->color.red = m->color.green = m->color.blue = 0xFFFF;
402
412
         m->color.blue = 0x1111; m->color.green = 0x8888;
403
413
         m->color.flags = DoRed | DoGreen | DoBlue;
404
 
         if (!XAllocColor (dpy, cmap, &m->color)) {
405
 
                m->color.pixel = WhitePixel (dpy, DefaultScreen (dpy));
 
414
         if (!XAllocColor (st->dpy, st->cmap, &m->color)) {
 
415
                m->color.pixel = WhitePixel (st->dpy, DefaultScreen (st->dpy));
406
416
                m->color.red = m->color.green = m->color.blue = 0xFFFF;
407
417
         }
408
418
  }
409
419
 
410
 
  gcv.foreground = default_fg_pixel =
411
 
    get_pixel_resource("foreground", "Foreground", dpy, cmap);
412
 
  gcv.font = scoreFont->fid;
413
 
  draw_gc = XCreateGC(dpy, window, GCForeground | GCFont, &gcv);
414
 
  gcv.font = font->fid;
415
 
  level_gc = XCreateGC(dpy, window, GCForeground | GCFont, &gcv);
416
 
  XSetForeground (dpy, level_gc, city[0].color.pixel);
417
 
  gcv.foreground = get_pixel_resource("background", "Background", dpy, cmap);
418
 
  erase_gc = XCreateGC(dpy, window, GCForeground, &gcv);
 
420
  gcv.foreground = st->default_fg_pixel =
 
421
    get_pixel_resource(st->dpy, st->cmap, "foreground", "Foreground");
 
422
  gcv.font = st->scoreFont->fid;
 
423
  st->draw_gc = XCreateGC(st->dpy, st->window, GCForeground | GCFont, &gcv);
 
424
  gcv.font = st->font->fid;
 
425
  st->level_gc = XCreateGC(st->dpy, st->window, GCForeground | GCFont, &gcv);
 
426
  XSetForeground (st->dpy, st->level_gc, st->city[0].color.pixel);
 
427
  gcv.foreground = get_pixel_resource(st->dpy, st->cmap, "background", "Background");
 
428
  st->erase_gc = XCreateGC(st->dpy, st->window, GCForeground, &gcv);
 
429
 
 
430
# ifdef HAVE_COCOA
 
431
  jwxyz_XSetAntiAliasing (st->dpy, st->erase_gc, False);
 
432
  jwxyz_XSetAntiAliasing (st->dpy, st->draw_gc, False);
 
433
# endif
 
434
 
419
435
 
420
436
  /* make a gray color for score */
421
437
  if (!mono_p) {
422
 
         scoreColor.red = scoreColor.green = scoreColor.blue = 0xAAAA;
423
 
         scoreColor.flags = DoRed | DoGreen | DoBlue;
424
 
         if (!XAllocColor (dpy, cmap, &scoreColor)) {
425
 
                scoreColor.pixel = WhitePixel (dpy, DefaultScreen (dpy));
426
 
                scoreColor.red = scoreColor.green = scoreColor.blue = 0xFFFF;
 
438
         st->scoreColor.red = st->scoreColor.green = st->scoreColor.blue = 0xAAAA;
 
439
         st->scoreColor.flags = DoRed | DoGreen | DoBlue;
 
440
         if (!XAllocColor (st->dpy, st->cmap, &st->scoreColor)) {
 
441
                st->scoreColor.pixel = WhitePixel (st->dpy, DefaultScreen (st->dpy));
 
442
                st->scoreColor.red = st->scoreColor.green = st->scoreColor.blue = 0xFFFF;
427
443
         }
428
444
  }
429
445
 
430
 
  XClearWindow(dpy, window);
431
 
  return cmap;
 
446
  XClearWindow(st->dpy, st->window);
 
447
  return st;
432
448
}
433
449
 
434
 
static void DrawScore(Display *dpy, Window window, Colormap cmap, int xlim, int ylim)
 
450
static void DrawScore(struct state *st, int xlim, int ylim)
435
451
{
436
452
  char buf[16];
437
453
  int width, height;
438
 
  sprintf(buf, "%ld", score);
439
 
  width = XTextWidth(scoreFont, buf, strlen(buf));
440
 
  height = font_height(scoreFont);
441
 
  XSetForeground (dpy, draw_gc, scoreColor.pixel);
442
 
  XFillRectangle(dpy, window, erase_gc,
 
454
  sprintf(buf, "%ld", st->score);
 
455
  width = XTextWidth(st->scoreFont, buf, strlen(buf));
 
456
  height = font_height(st->scoreFont);
 
457
  XSetForeground (st->dpy, st->draw_gc, st->scoreColor.pixel);
 
458
  XFillRectangle(st->dpy, st->window, st->erase_gc,
443
459
                                  xlim - width - 6, ylim - height - 2, width + 6, height + 2);
444
 
  XDrawString(dpy, window, draw_gc, xlim - width - 2, ylim - 2,
 
460
  XDrawString(st->dpy, st->window, st->draw_gc, xlim - width - 2, ylim - 2,
445
461
                    buf, strlen(buf));
446
462
 
447
 
  sprintf(buf, "%ld", highscore);
448
 
  width = XTextWidth(scoreFont, buf, strlen(buf));
449
 
  XFillRectangle(dpy, window, erase_gc,
 
463
  sprintf(buf, "%ld", st->highscore);
 
464
  width = XTextWidth(st->scoreFont, buf, strlen(buf));
 
465
  XFillRectangle(st->dpy, st->window, st->erase_gc,
450
466
                                  4, ylim - height - 2, width + 4, height + 2);
451
 
  XDrawString(dpy, window, draw_gc, 4, ylim - 2,
 
467
  XDrawString(st->dpy, st->window, st->draw_gc, 4, ylim - 2,
452
468
                    buf, strlen(buf));
453
469
}
454
470
 
455
 
static void AddScore(Display *dpy, Window window, Colormap cmap, int xlim, int ylim, long dif)
 
471
static void AddScore(struct state *st, int xlim, int ylim, long dif)
456
472
{
457
473
  int i, sumlive = 0;
458
474
  for (i=0;i<kNumCities;i++)
459
 
         sumlive += city[i].alive;
 
475
         sumlive += st->city[i].alive;
460
476
  if (sumlive == 0)
461
477
         return;   /* no cities, not possible to score */
462
478
 
463
 
  score += dif;
464
 
  if (score > highscore)
465
 
         highscore = score;
466
 
  DrawScore(dpy, window, cmap, xlim, ylim);
 
479
  st->score += dif;
 
480
  if (st->score > st->highscore)
 
481
         st->highscore = st->score;
 
482
  DrawScore(st, xlim, ylim);
467
483
}
468
484
 
469
 
static void DrawCity(Display *dpy, Window window, Colormap cmap, int x, int y, XColor col)
 
485
static void DrawCity(struct state *st, int x, int y, XColor col)
470
486
{
471
 
         XSetForeground (dpy, draw_gc, col.pixel);
472
 
         XFillRectangle(dpy, window, draw_gc,
 
487
         XSetForeground (st->dpy, st->draw_gc, col.pixel);
 
488
         XFillRectangle(st->dpy, st->window, st->draw_gc,
473
489
                                  x - 30, y - 40, 60, 40);
474
 
         XFillRectangle(dpy, window, draw_gc,
 
490
         XFillRectangle(st->dpy, st->window, st->draw_gc,
475
491
                                                 x - 20, y - 50, 10, 10);
476
 
         XFillRectangle(dpy, window, draw_gc,
 
492
         XFillRectangle(st->dpy, st->window, st->draw_gc,
477
493
                                  x + 10, y - 50, 10, 10);
478
494
}
479
495
 
480
 
static void DrawCities(Display *dpy, Window window, Colormap cmap, int xlim, int ylim)
 
496
static void DrawCities(struct state *st, int xlim, int ylim)
481
497
{
482
498
  int i, x;
483
499
  for (i = 0; i < kNumCities; i++) {
484
 
         City *m = &city[i];
 
500
         City *m = &st->city[i];
485
501
         if (!m->alive)
486
502
                continue;
487
503
         x = (i + 1) * (xlim / (kNumCities + 1));
488
504
         m->x = x;
489
505
 
490
 
         DrawCity(dpy, window, cmap, x, ylim, m->color);
 
506
         DrawCity(st, x, ylim, m->color);
491
507
  }
492
508
}
493
509
 
494
 
static void LoopMissiles(Display *dpy, Window window, Colormap cmap, int xlim, int ylim)
 
510
static void LoopMissiles(struct state *st, int xlim, int ylim)
495
511
{
496
512
  int i, j, max = 0;
497
513
  for (i = 0; i < kMaxMissiles; i++) {
498
514
         int old_x, old_y;
499
 
         Missile *m = &missile[i];
 
515
         Missile *m = &st->missile[i];
500
516
         if (!m->alive)
501
517
                continue;
502
518
         old_x = m->x;
507
523
 
508
524
      /* erase old one */
509
525
 
510
 
         XSetLineAttributes(dpy, draw_gc, 4, 0,0,0);
511
 
    XSetForeground (dpy, draw_gc, m->color.pixel);
512
 
         XDrawLine(dpy, window, draw_gc,
 
526
         XSetLineAttributes(st->dpy, st->draw_gc, 4, 0,0,0);
 
527
    XSetForeground (st->dpy, st->draw_gc, m->color.pixel);
 
528
         XDrawLine(st->dpy, st->window, st->draw_gc,
513
529
                                  old_x, old_y, m->x, m->y);
514
530
 
515
531
         /* maybe split off a new missile? */
516
532
         if (m->splits && (m->y > m->splits)) {
517
533
                m->splits = 0;
518
 
                launch(xlim, ylim, dpy, cmap, i);
 
534
                launch(st, xlim, ylim, i);
519
535
         }
520
536
         
521
537
         if (m->y >= ylim) {
522
538
                m->alive = 0;
523
 
                if (city[m->dcity].alive) {
524
 
                  city[m->dcity].alive = 0;
525
 
                  Explode(m->x, m->y, kBoomRad * 2, m->color, 0);
 
539
                if (st->city[m->dcity].alive) {
 
540
                  st->city[m->dcity].alive = 0;
 
541
                  Explode(st, m->x, m->y, kBoomRad * 2, m->color, 0);
526
542
                }
527
543
         }
528
544
 
529
545
         /* check hitting explosions */
530
546
         for (j=0;j<kMaxBooms;j++) {
531
 
                Boom *b = &boom[j];
 
547
                Boom *b = &st->boom[j];
532
548
                if (!b->alive)
533
549
                  continue;
534
550
                else {
538
554
                  if ((dx < r) && (dy < r))
539
555
                         if (dx * dx + dy * dy < r * r) {
540
556
                                m->alive = 0;
541
 
                                max = b->max + bgrowth - kBoomRad;
542
 
                                AddScore(dpy, window, cmap, xlim, ylim, SCORE_MISSILE);
 
557
                                max = b->max + st->bgrowth - kBoomRad;
 
558
                                AddScore(st, xlim, ylim, SCORE_MISSILE);
543
559
                  }
544
560
                }
545
561
         }
546
562
 
547
563
         if (m->alive == 0) {
548
 
                int old_x, old_y;
549
564
                float my_pos;
550
565
                /* we just died */
551
 
                Explode(m->x, m->y, kBoomRad + max, m->color, 0);
552
 
                XSetLineAttributes(dpy, erase_gc, 4, 0,0,0);
 
566
                Explode(st, m->x, m->y, kBoomRad + max, m->color, 0);
 
567
                XSetLineAttributes(st->dpy, st->erase_gc, 4, 0,0,0);
553
568
                /* In a perfect world, we could simply erase a line from
554
569
                   (m->startx, m->starty) to (m->x, m->y). This is not a
555
570
                   perfect world. */
559
574
                while (my_pos <= m->pos) {
560
575
                        m->x = m->startx + ((float) (m->endx - m->startx)) * my_pos;
561
576
                        m->y = m->starty + ((float) (m->endy - m->starty)) * my_pos;
562
 
                        XDrawLine(dpy, window, erase_gc, old_x, old_y, m->x, m->y);
 
577
                        XDrawLine(st->dpy, st->window, st->erase_gc, old_x, old_y, m->x, m->y);
563
578
                        old_x = m->x;
564
579
                        old_y = m->y;
565
580
                        my_pos += kMissileSpeed;
568
583
  }
569
584
}
570
585
 
571
 
static void LoopLasers(Display *dpy, Window window, Colormap cmap, int xlim, int ylim)
 
586
static void LoopLasers(struct state *st, int xlim, int ylim)
572
587
{
573
588
  int i, j, miny = ylim * 0.8;
574
589
  int x, y;
575
590
  for (i = 0; i < kMaxLasers; i++) {
576
 
         Laser *m = &laser[i];
 
591
         Laser *m = &st->laser[i];
577
592
         if (!m->alive)
578
593
                continue;
579
594
 
580
595
         if (m->oldx != -1) {
581
 
                 XSetLineAttributes(dpy, erase_gc, 2, 0,0,0);
582
 
                 XDrawLine(dpy, window, erase_gc,
 
596
                 XSetLineAttributes(st->dpy, st->erase_gc, 2, 0,0,0);
 
597
                 XDrawLine(st->dpy, st->window, st->erase_gc,
583
598
                                  m->oldx2, m->oldy2, m->oldx, m->oldy);
584
599
         }
585
600
 
594
609
         m->oldx = x;
595
610
         m->oldy = y;
596
611
 
597
 
         XSetLineAttributes(dpy, draw_gc, 2, 0,0,0);
598
 
    XSetForeground (dpy, draw_gc, m->color.pixel);
599
 
         XDrawLine(dpy, window, draw_gc,
 
612
         XSetLineAttributes(st->dpy, st->draw_gc, 2, 0,0,0);
 
613
    XSetForeground (st->dpy, st->draw_gc, m->color.pixel);
 
614
         XDrawLine(st->dpy, st->window, st->draw_gc,
600
615
                                  m->x, m->y, x, y);
601
616
 
602
617
         m->oldx2 = m->x;
611
626
         /* check hitting explosions */
612
627
         if (m->y < miny)
613
628
                for (j=0;j<kMaxBooms;j++) {
614
 
                  Boom *b = &boom[j];
 
629
                  Boom *b = &st->boom[j];
615
630
                  if (!b->alive)
616
631
                         continue;
617
632
                  else {
624
639
                                if (dx * dx + dy * dy < r * r) {
625
640
                                  m->alive = 0;
626
641
                                  /* one less enemy on this missile -- it probably didn't make it */
627
 
                                  if (missile[m->target].alive)
628
 
                                         missile[m->target].enemies--;
 
642
                                  if (st->missile[m->target].alive)
 
643
                                         st->missile[m->target].enemies--;
629
644
                                }
630
645
                  }
631
646
                }
632
647
         
633
648
         if (m->alive == 0) {
634
649
                /* we just died */
635
 
                XDrawLine(dpy, window, erase_gc,
 
650
                XDrawLine(st->dpy, st->window, st->erase_gc,
636
651
                                  m->x, m->y, x, y);
637
 
                Explode(m->x, m->y, kBoomRad, m->color, 1);
 
652
                Explode(st, m->x, m->y, kBoomRad, m->color, 1);
638
653
         }
639
654
  }
640
655
}
641
656
 
642
 
static void LoopBooms(Display *dpy, Window window, Colormap cmap, int xlim, int ylim)
 
657
static void LoopBooms(struct state *st, int xlim, int ylim)
643
658
{
644
659
  int i;
645
660
  for (i = 0; i < kMaxBooms; i++) {
646
 
         Boom *m = &boom[i];
 
661
         Boom *m = &st->boom[i];
647
662
         if (!m->alive)
648
663
                continue;
649
664
         
650
 
         if (loop & 1) {
 
665
         if (st->loop & 1) {
651
666
                if (m->outgoing) {
652
667
                  m->rad++;
653
668
                  if (m->rad >= m->max)
654
669
                         m->outgoing = 0;
655
 
                  XSetLineAttributes(dpy, draw_gc, 1, 0,0,0);
656
 
                  XSetForeground (dpy, draw_gc, m->color.pixel);
657
 
                  XDrawArc(dpy, window, draw_gc, m->x - m->rad, m->y - m->rad, m->rad * 2, m->rad * 2, 0, 360 * 64);
 
670
                  XSetLineAttributes(st->dpy, st->draw_gc, 1, 0,0,0);
 
671
                  XSetForeground (st->dpy, st->draw_gc, m->color.pixel);
 
672
                  XDrawArc(st->dpy, st->window, st->draw_gc, m->x - m->rad, m->y - m->rad, m->rad * 2, m->rad * 2, 0, 360 * 64);
658
673
                }
659
674
                else {
660
 
                  XSetLineAttributes(dpy, erase_gc, 1, 0,0,0);
661
 
                  XDrawArc(dpy, window, erase_gc, m->x - m->rad, m->y - m->rad, m->rad * 2, m->rad * 2, 0, 360 * 64);
 
675
                  XSetLineAttributes(st->dpy, st->erase_gc, 1, 0,0,0);
 
676
                  XDrawArc(st->dpy, st->window, st->erase_gc, m->x - m->rad, m->y - m->rad, m->rad * 2, m->rad * 2, 0, 360 * 64);
662
677
                  m->rad--;
663
678
                  if (m->rad <= 0)
664
679
                         m->alive = 0;
667
682
  }
668
683
}
669
684
 
670
 
int level = 0, levMissiles, levFreq;
671
685
 
672
686
/* after they die, let's change a few things */
673
 
static void Improve(void)
 
687
static void Improve(struct state *st)
674
688
{
675
 
  if (smart)
 
689
  if (st->smart)
676
690
         return;
677
 
  if (level > 20)
 
691
  if (st->level > 20)
678
692
         return;  /* no need, really */
679
 
  aim -= 4;
680
 
  if (level <= 2) aim -= 8;
681
 
  if (level <= 5) aim -= 6;
682
 
  if (gamez < 3)
683
 
         aim -= 10;
684
 
  carefulpersen += 6;
685
 
  choosypersen += 4;
686
 
  if (level <= 5) choosypersen += 3;
687
 
  econpersen += 4;
688
 
  lrate -= 2;
689
 
  if (startlrate < kMinRate) {
690
 
         if (lrate < startlrate)
691
 
                lrate = startlrate;
 
693
  st->aim -= 4;
 
694
  if (st->level <= 2) st->aim -= 8;
 
695
  if (st->level <= 5) st->aim -= 6;
 
696
  if (st->gamez < 3)
 
697
         st->aim -= 10;
 
698
  st->carefulpersen += 6;
 
699
  st->choosypersen += 4;
 
700
  if (st->level <= 5) st->choosypersen += 3;
 
701
  st->econpersen += 4;
 
702
  st->lrate -= 2;
 
703
  if (st->startlrate < kMinRate) {
 
704
         if (st->lrate < st->startlrate)
 
705
                st->lrate = st->startlrate;
692
706
  }
693
707
  else {
694
 
         if (lrate < kMinRate)
695
 
                lrate = kMinRate;
 
708
         if (st->lrate < kMinRate)
 
709
                st->lrate = kMinRate;
696
710
  }
697
 
  if (level <= 5) econpersen += 3;
698
 
  if (aim < 1) aim = 1;
699
 
  if (choosypersen > 100) choosypersen = 100;
700
 
  if (carefulpersen > 100) carefulpersen = 100;
701
 
  if (econpersen > 100) econpersen = 100;
 
711
  if (st->level <= 5) st->econpersen += 3;
 
712
  if (st->aim < 1) st->aim = 1;
 
713
  if (st->choosypersen > 100) st->choosypersen = 100;
 
714
  if (st->carefulpersen > 100) st->carefulpersen = 100;
 
715
  if (st->econpersen > 100) st->econpersen = 100;
702
716
}
703
717
 
704
 
static void NewLevel(Display *dpy, Window window, Colormap cmap, int xlim, int ylim)
 
718
static void NewLevel(struct state *st, int xlim, int ylim)
705
719
{
706
720
  char buf[32];
707
721
  int width, i, sumlive = 0;
708
722
  int liv[kNumCities];
709
723
  int freecity = 0;
710
724
 
711
 
  if (level == 0) {
712
 
         level++;
 
725
  if (st->level == 0) {
 
726
         st->level++;
713
727
         goto END_LEVEL;
714
728
  }
715
729
 
716
730
  /* check for a free city */
717
 
  if (score >= nextBonus) {
718
 
         numBonus++;
719
 
         nextBonus += kFirstBonus * numBonus;
 
731
  if (st->score >= st->nextBonus) {
 
732
         st->numBonus++;
 
733
         st->nextBonus += kFirstBonus * st->numBonus;
720
734
         freecity = 1;
721
735
  }
722
736
 
723
737
  for (i=0;i<kNumCities;i++) {
724
 
         if (bround)
725
 
                city[i].alive = blive[i];
726
 
         liv[i] = city[i].alive;
 
738
         if (st->bround)
 
739
                st->city[i].alive = st->blive[i];
 
740
         liv[i] = st->city[i].alive;
727
741
         sumlive += liv[i];
728
 
         if (!bround)
729
 
                city[i].alive = 0;
 
742
         if (!st->bround)
 
743
                st->city[i].alive = 0;
730
744
  }
731
745
 
732
746
  /* print out screen */
733
 
  XFillRectangle(dpy, window, erase_gc,
 
747
  XFillRectangle(st->dpy, st->window, st->erase_gc,
734
748
                                  0, 0, xlim, ylim);
735
 
  if (bround)
 
749
  if (st->bround)
736
750
         sprintf(buf, "Bonus Round Over");
737
751
  else {
738
752
         if (sumlive || freecity)
739
 
                sprintf(buf, "Level %d Cleared", level);
 
753
                sprintf(buf, "Level %d Cleared", st->level);
740
754
         else
741
755
                sprintf(buf, "GAME OVER");
742
756
  }
743
 
  if (level > 0) {
744
 
         width = XTextWidth(font, buf, strlen(buf));
745
 
         XDrawString(dpy, window, level_gc, xlim / 2 - width / 2, ylim / 2 - font_height(font) / 2,
 
757
  if (st->level > 0) {
 
758
         width = XTextWidth(st->font, buf, strlen(buf));
 
759
         XDrawString(st->dpy, st->window, st->level_gc, xlim / 2 - width / 2, ylim / 2 - font_height(st->font) / 2,
746
760
                                         buf, strlen(buf));
747
 
         XSync(dpy, False);
748
 
         screenhack_handle_events(dpy);
749
 
         sleep(1);
 
761
         XSync(st->dpy, False);
 
762
         usleep(1000000);
750
763
  }
751
764
 
752
 
  if (!bround) {
 
765
  if (!st->bround) {
753
766
         if (sumlive || freecity) {
754
767
                int sumwidth;
755
768
                /* draw live cities */
756
 
                XFillRectangle(dpy, window, erase_gc,
 
769
                XFillRectangle(st->dpy, st->window, st->erase_gc,
757
770
                                                        0, ylim - 100, xlim, 100);
758
771
 
759
 
                sprintf(buf, "X %ld", level * 100L);
 
772
                sprintf(buf, "X %ld", st->level * 100L);
760
773
                /* how much they get */
761
 
                sumwidth = XTextWidth(font, buf, strlen(buf));
 
774
                sumwidth = XTextWidth(st->font, buf, strlen(buf));
762
775
                /* add width of city */
763
776
                sumwidth += 60;
764
777
                /* add spacer */
765
778
                sumwidth += 40;
766
 
                DrawCity(dpy, window, cmap, xlim / 2 - sumwidth / 2 + 30, ylim * 0.70, city[0].color);
767
 
                XDrawString(dpy, window, level_gc, xlim / 2 - sumwidth / 2 + 40 + 60, ylim * 0.7, buf, strlen(buf));
 
779
                DrawCity(st, xlim / 2 - sumwidth / 2 + 30, ylim * 0.70, st->city[0].color);
 
780
                XDrawString(st->dpy, st->window, st->level_gc, xlim / 2 - sumwidth / 2 + 40 + 60, ylim * 0.7, buf, strlen(buf));
768
781
                for (i=0;i<kNumCities;i++) {
769
782
                  if (liv[i]) {
770
 
                         city[i].alive = 1;
771
 
                         AddScore(dpy, window, cmap, xlim, ylim, 100 * level);
772
 
                         DrawCities(dpy, window, cmap, xlim, ylim);
773
 
                         XSync(dpy, False);
774
 
                         screenhack_handle_events(dpy);
 
783
                         st->city[i].alive = 1;
 
784
                         AddScore(st, xlim, ylim, 100 * st->level);
 
785
                         DrawCities(st, xlim, ylim);
 
786
                         XSync(st->dpy, False);
775
787
                         usleep(kCityPause);
776
788
                  }
777
789
                }
778
790
         }
779
791
         else {
780
792
                /* we're dead */
781
 
                screenhack_handle_events(dpy);
782
 
                sleep(3);
783
 
                screenhack_handle_events(dpy);
 
793
                usleep(3000000);
 
794
 
784
795
                /* start new */
785
 
                gamez++;
786
 
                Improve();
 
796
                st->gamez++;
 
797
                Improve(st);
787
798
                for (i=0;i<kNumCities;i++)
788
 
                  city[i].alive = 1;
789
 
                level = 0;
790
 
                loop = 1;
791
 
                score = 0;
792
 
                nextBonus = kFirstBonus;
793
 
                numBonus = 0;
794
 
                DrawCities(dpy, window, cmap, xlim, ylim);
 
799
                  st->city[i].alive = 1;
 
800
                st->level = 0;
 
801
                st->loop = 1;
 
802
                st->score = 0;
 
803
                st->nextBonus = kFirstBonus;
 
804
                st->numBonus = 0;
 
805
                DrawCities(st, xlim, ylim);
795
806
         }
796
807
  }
797
808
 
799
810
  if (freecity && sumlive < 5) {
800
811
         int ncnt = random() % (5 - sumlive) + 1;
801
812
         for (i=0;i<kNumCities;i++)
802
 
                if (!city[i].alive)
 
813
                if (!st->city[i].alive)
803
814
                  if (!--ncnt)
804
 
                         city[i].alive = 1;
 
815
                         st->city[i].alive = 1;
805
816
         strcpy(buf, "Bonus City");
806
 
         width = XTextWidth(font, buf, strlen(buf));
807
 
         XDrawString(dpy, window, level_gc, xlim / 2 - width / 2, ylim / 4, buf, strlen(buf));
808
 
         DrawCities(dpy, window, cmap, xlim, ylim);
809
 
         XSync(dpy, False);
810
 
         screenhack_handle_events(dpy);
811
 
         sleep(1);
 
817
         width = XTextWidth(st->font, buf, strlen(buf));
 
818
         XDrawString(st->dpy, st->window, st->level_gc, xlim / 2 - width / 2, ylim / 4, buf, strlen(buf));
 
819
         DrawCities(st, xlim, ylim);
 
820
         XSync(st->dpy, False);
 
821
         usleep(1000000);
812
822
  }
813
823
 
814
 
  XFillRectangle(dpy, window, erase_gc,
 
824
  XFillRectangle(st->dpy, st->window, st->erase_gc,
815
825
                                          0, 0, xlim, ylim - 100);
816
826
  
817
 
  if (!bround)
818
 
         level++;
819
 
  if (level == 1) {
820
 
         nextBonus = kFirstBonus;
 
827
  if (!st->bround)
 
828
         st->level++;
 
829
  if (st->level == 1) {
 
830
         st->nextBonus = kFirstBonus;
821
831
  }
822
832
 
823
 
  if (level > 3 && (level % 5 == 1)) {
824
 
         if (bround) {
825
 
                bround = 0;
826
 
                DrawCities(dpy, window, cmap, xlim, ylim);
 
833
  if (st->level > 3 && (st->level % 5 == 1)) {
 
834
         if (st->bround) {
 
835
                st->bround = 0;
 
836
                DrawCities(st, xlim, ylim);
827
837
         }
828
838
         else {
829
839
                /* bonus round */
830
 
                bround = 1;
831
 
                levMissiles = 20 + level * 10;
832
 
                levFreq = 10;
 
840
                st->bround = 1;
 
841
                st->levMissiles = 20 + st->level * 10;
 
842
                st->levFreq = 10;
833
843
                for (i=0;i<kNumCities;i++)
834
 
                  blive[i] = city[i].alive;
 
844
                  st->blive[i] = st->city[i].alive;
835
845
                sprintf(buf, "Bonus Round");
836
 
                width = XTextWidth(font, buf, strlen(buf));
837
 
                XDrawString(dpy, window, level_gc, xlim / 2 - width / 2, ylim / 2 - font_height(font) / 2, buf, strlen(buf));
838
 
                XSync(dpy, False);
839
 
                screenhack_handle_events(dpy);
840
 
                sleep(1);
841
 
                XFillRectangle(dpy, window, erase_gc,
 
846
                width = XTextWidth(st->font, buf, strlen(buf));
 
847
                XDrawString(st->dpy, st->window, st->level_gc, xlim / 2 - width / 2, ylim / 2 - font_height(st->font) / 2, buf, strlen(buf));
 
848
                XSync(st->dpy, False);
 
849
                usleep(1000000);
 
850
                XFillRectangle(st->dpy, st->window, st->erase_gc,
842
851
                                                        0, 0, xlim, ylim - 100);
843
852
         }
844
853
  }
845
854
 
846
855
 END_LEVEL: ;
847
856
 
848
 
  if (!bround) {
849
 
         levMissiles = 5 + level * 3;
850
 
         if (level > 5)
851
 
                levMissiles += level * 5;
 
857
  if (!st->bround) {
 
858
         st->levMissiles = 5 + st->level * 3;
 
859
         if (st->level > 5)
 
860
                st->levMissiles += st->level * 5;
852
861
         /*  levMissiles = 2; */
853
 
         levFreq = 120 - level * 5;
854
 
         if (levFreq < 30)
855
 
                levFreq = 30;
 
862
         st->levFreq = 120 - st->level * 5;
 
863
         if (st->levFreq < 30)
 
864
                st->levFreq = 30;
856
865
  }
857
866
 
858
867
  /* ready to fire */
859
 
  lastLaser = 0;
 
868
  st->lastLaser = 0;
860
869
}
861
870
 
862
 
static void penetrate(Display *dpy, Window window, Colormap cmap)
 
871
 
 
872
static unsigned long
 
873
penetrate_draw (Display *dpy, Window window, void *closure)
863
874
{
 
875
  struct state *st = (struct state *) closure;
864
876
  XWindowAttributes xgwa;
865
 
  static int xlim, ylim;
866
 
 
867
 
  XGetWindowAttributes(dpy, window, &xgwa);
868
 
  xlim = xgwa.width;
869
 
  ylim = xgwa.height;
 
877
 
 
878
  if (st->draw_reset)
 
879
    {
 
880
      st->draw_reset = 0;
 
881
      DrawCities(st, st->draw_xlim, st->draw_ylim);
 
882
    }
 
883
 
 
884
  XGetWindowAttributes(st->dpy, st->window, &xgwa);
 
885
  st->draw_xlim = xgwa.width;
 
886
  st->draw_ylim = xgwa.height;
870
887
 
871
888
  /* see if just started */
872
 
  if (loop == 0) {
873
 
         if (smart) {
874
 
                choosypersen = econpersen = carefulpersen = 100;
875
 
                lrate = kMinRate; aim = 1;
 
889
  if (st->loop == 0) {
 
890
         if (st->smart) {
 
891
                st->choosypersen = st->econpersen = st->carefulpersen = 100;
 
892
                st->lrate = kMinRate; st->aim = 1;
876
893
         }
877
 
         NewLevel(dpy, window, cmap, xlim, ylim);
878
 
         DrawScore(dpy, window, cmap, xlim, ylim);
 
894
         NewLevel(st, st->draw_xlim, st->draw_ylim);
 
895
         DrawScore(st, st->draw_xlim, st->draw_ylim);
879
896
  }
880
897
 
881
 
  loop++;
 
898
  st->loop++;
882
899
 
883
 
  if (levMissiles == 0) {
 
900
  if (st->levMissiles == 0) {
884
901
         /* see if anything's still on the screen, to know when to end level */
885
902
         int i;
886
903
         for (i=0;i<kMaxMissiles;i++)
887
 
                if (missile[i].alive)
 
904
                if (st->missile[i].alive)
888
905
                  goto END_CHECK;
889
906
         for (i=0;i<kMaxBooms;i++)
890
 
                if (boom[i].alive)
 
907
                if (st->boom[i].alive)
891
908
                  goto END_CHECK;
892
909
         for (i=0;i<kMaxLasers;i++)
893
 
                if (laser[i].alive)
 
910
                if (st->laser[i].alive)
894
911
                  goto END_CHECK;
895
912
         /* okay, nothing's alive, start end of level countdown */
896
 
         screenhack_handle_events(dpy);
897
 
         sleep(kLevelPause);
898
 
         NewLevel(dpy, window, cmap, xlim, ylim);
899
 
         return;
 
913
         usleep(kLevelPause*1000000);
 
914
         NewLevel(st, st->draw_xlim, st->draw_ylim);
 
915
         goto END;
900
916
  END_CHECK: ;
901
917
  }
902
 
  else if ((random() % levFreq) == 0) {
903
 
         launch(xlim, ylim, dpy, cmap, -1);
904
 
         levMissiles--;
905
 
  }
906
 
 
907
 
  if (loop - lastLaser >= lrate) {
908
 
         if (fire(xlim, ylim, dpy, window, cmap))
909
 
                lastLaser = loop;
910
 
  }
911
 
 
912
 
  XSync(dpy, False);
913
 
  screenhack_handle_events(dpy);
914
 
  if (kSleepTime)
915
 
         usleep(kSleepTime);
916
 
 
917
 
  if ((loop & 7) == 0)
918
 
         DrawCities(dpy, window, cmap, xlim, ylim);
919
 
  LoopMissiles(dpy, window, cmap, xlim, ylim);
920
 
  LoopLasers(dpy, window, cmap, xlim, ylim);
921
 
  LoopBooms(dpy, window, cmap, xlim, ylim);
922
 
}
923
 
 
924
 
char *progclass = "Penetrate";
925
 
 
926
 
char *defaults [] = {
 
918
  else if ((random() % st->levFreq) == 0) {
 
919
         launch(st, st->draw_xlim, st->draw_ylim, -1);
 
920
         st->levMissiles--;
 
921
  }
 
922
 
 
923
  if (st->loop - st->lastLaser >= st->lrate) {
 
924
         if (fire(st, st->draw_xlim, st->draw_ylim))
 
925
                st->lastLaser = st->loop;
 
926
  }
 
927
 
 
928
  if ((st->loop & 7) == 0)
 
929
    st->draw_reset = 1;
 
930
 
 
931
  LoopMissiles(st, st->draw_xlim, st->draw_ylim);
 
932
  LoopLasers(st, st->draw_xlim, st->draw_ylim);
 
933
  LoopBooms(st, st->draw_xlim, st->draw_ylim);
 
934
 
 
935
 END:
 
936
  return kSleepTime;
 
937
}
 
938
 
 
939
static void
 
940
penetrate_reshape (Display *dpy, Window window, void *closure, 
 
941
                 unsigned int w, unsigned int h)
 
942
{
 
943
}
 
944
 
 
945
static Bool
 
946
penetrate_event (Display *dpy, Window window, void *closure, XEvent *event)
 
947
{
 
948
  return False;
 
949
}
 
950
 
 
951
static void
 
952
penetrate_free (Display *dpy, Window window, void *closure)
 
953
{
 
954
  struct state *st = (struct state *) closure;
 
955
  free (st);
 
956
}
 
957
 
 
958
 
 
959
static const char *penetrate_defaults [] = {
927
960
  ".background: black",
928
961
  ".foreground: white",
929
962
  "*bgrowth:    5",
930
963
  "*lrate:      80",
 
964
  "*smart:      False",
931
965
  "*geometry:   800x500",
932
966
  0
933
967
};
934
968
 
935
 
XrmOptionDescRec options [] = {
 
969
static XrmOptionDescRec penetrate_options [] = {
936
970
  { "-bgrowth",         ".bgrowth",     XrmoptionSepArg, 0 },
937
971
  { "-lrate",           ".lrate",       XrmoptionSepArg, 0 },
938
 
        {"-smart", ".smart", XrmoptionIsArg,0},
 
972
  {"-smart",            ".smart",       XrmoptionNoArg, "True" },
939
973
  { 0, 0, 0, 0 }
940
974
};
941
975
 
942
 
void
943
 
screenhack (Display *dpy, Window window)
944
 
{
945
 
  Colormap cmap = init_penetrate(dpy, window);
946
 
  while (1)
947
 
    penetrate(dpy, window, cmap);
948
 
}
 
976
XSCREENSAVER_MODULE ("Penetrate", penetrate)