+++ /dev/null
-/* Copyright (c) 1999
- * Adam Miller adum@aya.yale.edu
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation. No representations are made about the suitability of this
- * software for any purpose. It is provided "as is" without express or
- * implied warranty.
-
- * penetrate simulates the arcade classic with the cities and the stuff
- * shooting down from the sky and stuff. The computer plays against itself,
- * desperately defending the forces of good against those thingies raining
- * down. Bonus cities are awarded at ever-increasing intervals. Every five
- * levels appears a bonus round. The computer player gets progressively
- * more intelligent as the game progresses. Better aim, more economical with
- * ammo, and better target selection. Points are in the bottom right, and
- * high score is in the bottom left. Start with -smart to have the computer
- * player skip the learning process.
-
- */
-
-#include "screenhack.h"
-
-#define kSleepTime 10000
-
-#define font_height(font) (font->ascent + font->descent)
-#define FONT_NAME "-*-times-*-*-*-*-80-*-*-*-*-*-*-*"
-
-#define kCityPause 500000
-#define kLevelPause 1
-#define SCORE_MISSILE 100
-#define kFirstBonus 5000
-#define kMinRate 30
-#define kMaxRadius 100
-
-static XFontStruct *font, *scoreFont;
-static GC draw_gc, erase_gc, level_gc;
-static unsigned int default_fg_pixel;
-static XColor scoreColor;
-
-int bgrowth;
-int lrate = 80, startlrate;
-long loop = 0;
-long score = 0, highscore = 0;
-long nextBonus = kFirstBonus;
-int numBonus = 0;
-int bround = 0;
-long lastLaser = 0;
-int gamez = 0;
-int aim = 180;
-int econpersen = 0;
-int choosypersen = 0;
-int carefulpersen = 0;
-int smart = 0;
-
-typedef struct {
- int alive;
- int x, y;
- int startx, starty;
- int endx, endy;
- int dcity;
- float pos;
- int enemies;
- int jenis;
- int splits;
- XColor color;
-} Missile;
-
-typedef struct {
- int alive;
- int x, y, rad, oflaser;
- int max, outgoing;
- XColor color;
-} Boom;
-
-typedef struct {
- int alive;
- int x;
- XColor color;
-} City;
-
-typedef struct {
- int alive;
- int x, y;
- int startx, starty;
- int endx, endy;
- int oldx, oldy;
- float velx, vely, fposx, fposy;
- float lenMul;
- XColor color;
- int target;
-} Laser;
-
-#define kMaxMissiles 256
-#define kMaxBooms 512
-#define kMaxLasers 128
-#define kBoomRad 40
-#define kNumCities 5
-
-#define kLaserLength 12
-
-#define kMissileSpeed 0.003
-#define kLaserSpeed (kMissileSpeed * 6)
-
-Missile missile[kMaxMissiles];
-Boom boom[kMaxBooms];
-City city[kNumCities];
-Laser laser[kMaxLasers];
-int blive[kNumCities];
-
-static void Explode(int x, int y, int max, XColor color, int oflaser)
-{
- int i;
- Boom *m = 0;
- for (i=0;i<kMaxBooms;i++)
- if (!boom[i].alive) {
- m = &boom[i];
- break;
- }
- if (!m)
- return;
-
- m->alive = 1;
- m->x = x;
- m->y = y;
- m->rad = 0;
- if (max > kMaxRadius)
- max = kMaxRadius;
- m->max = max;
- m->outgoing = 1;
- m->color = color;
- m->oflaser = oflaser;
-}
-
-static void launch (int xlim, int ylim,
- Display *dpy, Colormap cmap, int src)
-{
- int i;
- Missile *m = 0, *msrc;
- for (i=0;i<kMaxMissiles;i++)
- if (!missile[i].alive) {
- m = &missile[i];
- break;
- }
- if (!m)
- return;
-
- m->alive = 1;
- m->startx = (random() % xlim);
- m->starty = 0;
- m->endy = ylim;
- m->pos = 0.0;
- m->jenis = random() % 360;
- m->splits = 0;
- if (m->jenis < 50) {
- m->splits = random() % ((int) (ylim * 0.4));
- if (m->splits < ylim * 0.08)
- m->splits = 0;
- }
-
- /* special if we're from another missile */
- if (src >= 0) {
- int dc = random() % (kNumCities - 1);
- msrc = &missile[src];
- if (dc == msrc->dcity)
- dc++;
- m->dcity = dc;
- m->startx = msrc->x;
- m->starty = msrc->y;
- if (m->starty > ylim * 0.4 || m->splits <= m->starty)
- m->splits = 0; /* too far down already */
- m->jenis = msrc->jenis;
- }
- else
- m->dcity = random() % kNumCities;
- m->endx = city[m->dcity].x + (random() % 20) - 10;
- m->x = m->startx;
- m->y = m->starty;
- m->enemies = 0;
-
- if (!mono_p) {
- hsv_to_rgb (m->jenis, 1.0, 1.0,
- &m->color.red, &m->color.green, &m->color.blue);
- m->color.flags = DoRed | DoGreen | DoBlue;
- if (!XAllocColor (dpy, cmap, &m->color)) {
- m->color.pixel = WhitePixel (dpy, DefaultScreen (dpy));
- m->color.red = m->color.green = m->color.blue = 0xFFFF;
- }
- }
-}
-
-static int fire(int xlim, int ylim,
- Display *dpy, Window window, Colormap cmap)
-{
- int i, j, cnt = 0;
- int dcity;
- long dx, dy, ex, ey;
- Missile *mis = 0;
- Laser *m = 0;
- int untargeted = 0;
- int choosy = 0, economic = 0, careful = 0;
- int suitor[kMaxMissiles];
- int livecity = 0;
- int ytargetmin = ylim * 0.75;
- int deepest = 0;
- int misnum = 0;
-
- choosy = (random() % 100) < choosypersen;
- economic = (random() % 100) < econpersen;
- careful = (random() % 100) < carefulpersen;
-
- /* count our cities */
- for (i=0;i<kNumCities;i++)
- livecity += city[i].alive;
- if (livecity == 0)
- return 1; /* no guns */
-
- for (i=0;i<kMaxLasers;i++)
- if (!laser[i].alive) {
- m = &laser[i];
- break;
- }
- if (!m)
- return 1;
-
- /* if no missiles on target, no need to be choosy */
- if (choosy) {
- int choo = 0;
- for (j=0;j<kMaxMissiles;j++) {
- mis = &missile[j];
- if (!mis->alive || (mis->y > ytargetmin))
- continue;
- if (city[mis->dcity].alive)
- choo++;
- }
- if (choo == 0)
- choosy = 0;
- }
-
- for (j=0;j<kMaxMissiles;j++) {
- mis = &missile[j];
- suitor[j] = 0;
- if (!mis->alive || (mis->y > ytargetmin))
- continue;
- if (choosy && (city[mis->dcity].alive == 0))
- continue;
- cnt++;
- suitor[j] = 1;
- }
-
- /* count missiles that are on target and not being targeted */
- if (choosy && economic)
- for (j=0;j<kMaxMissiles;j++)
- if (suitor[j] && missile[j].enemies == 0)
- untargeted++;
-
- if (economic)
- for (j=0;j<kMaxMissiles;j++) {
- if (suitor[j] && cnt > 1)
- if (missile[j].enemies > 0)
- if (missile[j].enemies > 1 || untargeted == 0) {
- suitor[j] = 0;
- cnt--;
- }
- /* who's closest? biggest threat */
- if (suitor[j] && missile[j].y > deepest)
- deepest = missile[j].y;
- }
-
- if (deepest > 0 && careful) {
- /* only target deepest missile */
- cnt = 1;
- for (j=0;j<kMaxMissiles;j++)
- if (suitor[j] && missile[j].y != deepest)
- suitor[j] = 0;
- }
-
- if (cnt == 0)
- return 1; /* no targets available */
- cnt = random() % cnt;
- for (j=0;j<kMaxMissiles;j++)
- if (suitor[j])
- if (cnt-- == 0) {
- mis = &missile[j];
- misnum = j;
- break;
- }
-
- if (mis == 0)
- return 1; /* shouldn't happen */
-
- dcity = random() % livecity;
- for (j=0;j<kNumCities;j++)
- if (city[j].alive)
- if (dcity-- == 0) {
- dcity = j;
- break;
- }
- m->startx = city[dcity].x;
- m->starty = ylim;
-#define kExpHelp 0.2
-#define kSpeedDiff 3.5
- ex = mis->startx + ((float) (mis->endx - mis->startx)) * (mis->pos + kExpHelp + (1.0 - mis->pos) / kSpeedDiff);
- ey = mis->starty + ((float) (mis->endy - mis->starty)) * (mis->pos + kExpHelp + (1.0 - mis->pos) / kSpeedDiff);
- m->endx = ex + random() % 16 - 8 + (random() % aim) - aim / 2;
- m->endy = ey + random() % 16 - 8 + (random() % aim) - aim / 2;
- if (ey > ylim * 0.75)
- return 0; /* too far down */
- mis->enemies++;
- m->target = misnum;
- m->x = m->startx;
- m->y = m->starty;
- m->oldx = m->x;
- m->oldy = m->y;
- m->fposx = m->x;
- m->fposy = m->y;
- dx = (m->endx - m->x);
- dy = (m->endy - m->y);
- m->velx = dx / 100.0;
- m->vely = dy / 100.0;
- m->alive = 1;
- /* m->lenMul = (kLaserLength * kLaserLength) / (m->velx * m->velx + m->vely * m->vely); */
- m->lenMul = -(kLaserLength / m->vely);
-
- if (!mono_p) {
- m->color.blue = 0x0000;
- m->color.green = 0xFFFF;
- m->color.red = 0xFFFF;
- m->color.flags = DoRed | DoGreen | DoBlue;
- if (!XAllocColor (dpy, cmap, &m->color)) {
- m->color.pixel = WhitePixel (dpy, DefaultScreen (dpy));
- m->color.red = m->color.green = m->color.blue = 0xFFFF;
- }
- }
- return 1;
-}
-
-static Colormap
-init_penetrate(Display *dpy, Window window)
-{
- int i;
- /*char *fontname = "-*-new century schoolbook-*-r-*-*-*-380-*-*-*-*-*-*"; */
- char *fontname = "-*-courier-*-r-*-*-*-380-*-*-*-*-*-*";
- char **list;
- int foo;
- Colormap cmap;
- XGCValues gcv;
- XWindowAttributes xgwa;
- XGetWindowAttributes (dpy, window, &xgwa);
- cmap = xgwa.colormap;
-
- if (get_string_resource("smart","String")!=NULL && get_string_resource("smart","String")[0]!=0)
- smart = 1;
- bgrowth = get_integer_resource ("bgrowth", "Integer");
- lrate = get_integer_resource ("lrate", "Integer");
- if (bgrowth < 0) bgrowth = 2;
- if (lrate < 0) lrate = 2;
- startlrate = lrate;
-
- if (!fontname || !(font = XLoadQueryFont(dpy, fontname))) {
- list = XListFonts(dpy, FONT_NAME, 32767, &foo);
- for (i = 0; i < foo; i++)
- if ((font = XLoadQueryFont(dpy, list[i])))
- break;
- if (!font) {
- fprintf (stderr, "%s: Can't find a large font.", progname);
- exit (1);
- }
- XFreeFontNames(list);
- }
-
- if (!(scoreFont = XLoadQueryFont(dpy, "-*-times-*-r-*-*-*-180-*-*-*-*-*-*")))
- fprintf(stderr, "%s: Can't load Times font.", progname);
-
- for (i = 0; i < kMaxMissiles; i++)
- missile[i].alive = 0;
-
- for (i = 0; i < kMaxLasers; i++)
- laser[i].alive = 0;
-
- for (i = 0; i < kMaxBooms; i++)
- boom[i].alive = 0;
-
- for (i = 0; i < kNumCities; i++) {
- City *m = &city[i];
- m->alive = 1;
- m->color.red = m->color.green = m->color.blue = 0xFFFF;
- m->color.blue = 0x1111; m->color.green = 0x8888;
- m->color.flags = DoRed | DoGreen | DoBlue;
- if (!XAllocColor (dpy, cmap, &m->color)) {
- m->color.pixel = WhitePixel (dpy, DefaultScreen (dpy));
- m->color.red = m->color.green = m->color.blue = 0xFFFF;
- }
- }
-
- gcv.foreground = default_fg_pixel =
- get_pixel_resource("foreground", "Foreground", dpy, cmap);
- gcv.font = scoreFont->fid;
- draw_gc = XCreateGC(dpy, window, GCForeground | GCFont, &gcv);
- gcv.font = font->fid;
- level_gc = XCreateGC(dpy, window, GCForeground | GCFont, &gcv);
- XSetForeground (dpy, level_gc, city[0].color.pixel);
- gcv.foreground = get_pixel_resource("background", "Background", dpy, cmap);
- erase_gc = XCreateGC(dpy, window, GCForeground, &gcv);
-
- /* make a gray color for score */
- if (!mono_p) {
- scoreColor.red = scoreColor.green = scoreColor.blue = 0xAAAA;
- scoreColor.flags = DoRed | DoGreen | DoBlue;
- if (!XAllocColor (dpy, cmap, &scoreColor)) {
- scoreColor.pixel = WhitePixel (dpy, DefaultScreen (dpy));
- scoreColor.red = scoreColor.green = scoreColor.blue = 0xFFFF;
- }
- }
-
- XClearWindow(dpy, window);
- return cmap;
-}
-
-static void DrawScore(Display *dpy, Window window, Colormap cmap, int xlim, int ylim)
-{
- char buf[16];
- int width, height;
- sprintf(buf, "%ld", score);
- width = XTextWidth(scoreFont, buf, strlen(buf));
- height = font_height(scoreFont);
- XSetForeground (dpy, draw_gc, scoreColor.pixel);
- XFillRectangle(dpy, window, erase_gc,
- xlim - width - 6, ylim - height - 2, width + 6, height + 2);
- XDrawString(dpy, window, draw_gc, xlim - width - 2, ylim - 2,
- buf, strlen(buf));
-
- sprintf(buf, "%ld", highscore);
- width = XTextWidth(scoreFont, buf, strlen(buf));
- XFillRectangle(dpy, window, erase_gc,
- 4, ylim - height - 2, width + 4, height + 2);
- XDrawString(dpy, window, draw_gc, 4, ylim - 2,
- buf, strlen(buf));
-}
-
-static void AddScore(Display *dpy, Window window, Colormap cmap, int xlim, int ylim, long dif)
-{
- int i, sumlive = 0;
- for (i=0;i<kNumCities;i++)
- sumlive += city[i].alive;
- if (sumlive == 0)
- return; /* no cities, not possible to score */
-
- score += dif;
- if (score > highscore)
- highscore = score;
- DrawScore(dpy, window, cmap, xlim, ylim);
-}
-
-static void DrawCity(Display *dpy, Window window, Colormap cmap, int x, int y, XColor col)
-{
- XSetForeground (dpy, draw_gc, col.pixel);
- XFillRectangle(dpy, window, draw_gc,
- x - 30, y - 40, 60, 40);
- XFillRectangle(dpy, window, draw_gc,
- x - 20, y - 50, 10, 10);
- XFillRectangle(dpy, window, draw_gc,
- x + 10, y - 50, 10, 10);
-}
-
-static void DrawCities(Display *dpy, Window window, Colormap cmap, int xlim, int ylim)
-{
- int i, x;
- for (i = 0; i < kNumCities; i++) {
- City *m = &city[i];
- if (!m->alive)
- continue;
- x = (i + 1) * (xlim / (kNumCities + 1));
- m->x = x;
-
- DrawCity(dpy, window, cmap, x, ylim, m->color);
- }
-}
-
-static void LoopMissiles(Display *dpy, Window window, Colormap cmap, int xlim, int ylim)
-{
- int i, j, max = 0;
- for (i = 0; i < kMaxMissiles; i++) {
- int old_x, old_y;
- Missile *m = &missile[i];
- if (!m->alive)
- continue;
- old_x = m->x;
- old_y = m->y;
- m->pos += kMissileSpeed;
- m->x = m->startx + ((float) (m->endx - m->startx)) * m->pos;
- m->y = m->starty + ((float) (m->endy - m->starty)) * m->pos;
-
- /* erase old one */
-
- XSetLineAttributes(dpy, draw_gc, 4, 0,0,0);
- XSetForeground (dpy, draw_gc, m->color.pixel);
- XDrawLine(dpy, window, draw_gc,
- old_x, old_y, m->x, m->y);
-
- /* maybe split off a new missile? */
- if (m->splits && (m->y > m->splits)) {
- m->splits = 0;
- launch(xlim, ylim, dpy, cmap, i);
- }
-
- if (m->y >= ylim) {
- m->alive = 0;
- if (city[m->dcity].alive) {
- city[m->dcity].alive = 0;
- Explode(m->x, m->y, kBoomRad * 2, m->color, 0);
- }
- }
-
- /* check hitting explosions */
- for (j=0;j<kMaxBooms;j++) {
- Boom *b = &boom[j];
- if (!b->alive)
- continue;
- else {
- int dx = abs(m->x - b->x);
- int dy = abs(m->y - b->y);
- int r = b->rad + 2;
- if ((dx < r) && (dy < r))
- if (dx * dx + dy * dy < r * r) {
- m->alive = 0;
- max = b->max + bgrowth - kBoomRad;
- AddScore(dpy, window, cmap, xlim, ylim, SCORE_MISSILE);
- }
- }
- }
-
- if (m->alive == 0) {
- /* we just died */
- Explode(m->x, m->y, kBoomRad + max, m->color, 0);
- XSetLineAttributes(dpy, erase_gc, 5, 0,0,0);
- XDrawLine(dpy, window, erase_gc,
- m->startx, m->starty, m->x, m->y);
- }
- }
-}
-
-static void LoopLasers(Display *dpy, Window window, Colormap cmap, int xlim, int ylim)
-{
- int i, j, miny = ylim * 0.8;
- int x, y;
- for (i = 0; i < kMaxLasers; i++) {
- Laser *m = &laser[i];
- if (!m->alive)
- continue;
- m->fposx += m->velx;
- m->fposy += m->vely;
- m->x = m->fposx;
- m->y = m->fposy;
-
- x = m->fposx + (-m->velx * m->lenMul);
- y = m->fposy + (-m->vely * m->lenMul);
-
- XSetLineAttributes(dpy, erase_gc, 4, 0,0,0);
- XDrawLine(dpy, window, erase_gc,
- x, y, m->oldx, m->oldy);
- m->oldx = x;
- m->oldy = y;
-
- XSetLineAttributes(dpy, draw_gc, 2, 0,0,0);
- XSetForeground (dpy, draw_gc, m->color.pixel);
- XDrawLine(dpy, window, draw_gc,
- m->x, m->y, x, y);
-
- if (m->y < m->endy) {
- m->alive = 0;
- }
-
- /* check hitting explosions */
- if (m->y < miny)
- for (j=0;j<kMaxBooms;j++) {
- Boom *b = &boom[j];
- if (!b->alive)
- continue;
- else {
- int dx = abs(m->x - b->x);
- int dy = abs(m->y - b->y);
- int r = b->rad + 2;
- if (b->oflaser)
- continue;
- if ((dx < r) && (dy < r))
- if (dx * dx + dy * dy < r * r) {
- m->alive = 0;
- /* one less enemy on this missile -- it probably didn't make it */
- if (missile[m->target].alive)
- missile[m->target].enemies--;
- }
- }
- }
-
- if (m->alive == 0) {
- /* we just died */
- XDrawLine(dpy, window, erase_gc,
- m->x, m->y, x, y);
- Explode(m->x, m->y, kBoomRad, m->color, 1);
- }
- }
-}
-
-static void LoopBooms(Display *dpy, Window window, Colormap cmap, int xlim, int ylim)
-{
- int i;
- for (i = 0; i < kMaxBooms; i++) {
- Boom *m = &boom[i];
- if (!m->alive)
- continue;
-
- if (loop & 1)
- if (m->outgoing) {
- m->rad++;
- if (m->rad >= m->max)
- m->outgoing = 0;
- XSetLineAttributes(dpy, draw_gc, 1, 0,0,0);
- XSetForeground (dpy, draw_gc, m->color.pixel);
- XDrawArc(dpy, window, draw_gc, m->x - m->rad, m->y - m->rad, m->rad * 2, m->rad * 2, 0, 360 * 64);
- }
- else {
- XSetLineAttributes(dpy, erase_gc, 1, 0,0,0);
- XDrawArc(dpy, window, erase_gc, m->x - m->rad, m->y - m->rad, m->rad * 2, m->rad * 2, 0, 360 * 64);
- m->rad--;
- if (m->rad <= 0)
- m->alive = 0;
- }
- }
-}
-
-int level = 0, levMissiles, levFreq;
-
-/* after they die, let's change a few things */
-static void Improve(void)
-{
- if (smart)
- return;
- if (level > 20)
- return; /* no need, really */
- aim -= 4;
- if (level <= 2) aim -= 8;
- if (level <= 5) aim -= 6;
- if (gamez < 3)
- aim -= 10;
- carefulpersen += 6;
- choosypersen += 4;
- if (level <= 5) choosypersen += 3;
- econpersen += 4;
- lrate -= 2;
- if (startlrate < kMinRate) {
- if (lrate < startlrate)
- lrate = startlrate;
- }
- else {
- if (lrate < kMinRate)
- lrate = kMinRate;
- }
- if (level <= 5) econpersen += 3;
- if (aim < 1) aim = 1;
- if (choosypersen > 100) choosypersen = 100;
- if (carefulpersen > 100) carefulpersen = 100;
- if (econpersen > 100) econpersen = 100;
-}
-
-static void NewLevel(Display *dpy, Window window, Colormap cmap, int xlim, int ylim)
-{
- char buf[32];
- int width, i, sumlive = 0;
- int liv[kNumCities];
- int freecity = 0;
-
- if (level == 0) {
- level++;
- goto END_LEVEL;
- }
-
- /* check for a free city */
- if (score >= nextBonus) {
- numBonus++;
- nextBonus += kFirstBonus * numBonus;
- freecity = 1;
- }
-
- for (i=0;i<kNumCities;i++) {
- if (bround)
- city[i].alive = blive[i];
- liv[i] = city[i].alive;
- sumlive += liv[i];
- if (!bround)
- city[i].alive = 0;
- }
-
- /* print out screen */
- XFillRectangle(dpy, window, erase_gc,
- 0, 0, xlim, ylim);
- if (bround)
- sprintf(buf, "Bonus Round Over");
- else {
- if (sumlive || freecity)
- sprintf(buf, "Level %d Cleared", level);
- else
- sprintf(buf, "GAME OVER");
- }
- if (level > 0) {
- width = XTextWidth(font, buf, strlen(buf));
- XDrawString(dpy, window, level_gc, xlim / 2 - width / 2, ylim / 2 - font_height(font) / 2,
- buf, strlen(buf));
- XSync(dpy, False);
- screenhack_handle_events(dpy);
- sleep(1);
- }
-
- if (!bround) {
- if (sumlive || freecity) {
- int sumwidth;
- /* draw live cities */
- XFillRectangle(dpy, window, erase_gc,
- 0, ylim - 100, xlim, 100);
-
- sprintf(buf, "X %ld", level * 100L);
- /* how much they get */
- sumwidth = XTextWidth(font, buf, strlen(buf));
- /* add width of city */
- sumwidth += 60;
- /* add spacer */
- sumwidth += 40;
- DrawCity(dpy, window, cmap, xlim / 2 - sumwidth / 2 + 30, ylim * 0.70, city[0].color);
- XDrawString(dpy, window, level_gc, xlim / 2 - sumwidth / 2 + 40 + 60, ylim * 0.7, buf, strlen(buf));
- for (i=0;i<kNumCities;i++) {
- if (liv[i]) {
- city[i].alive = 1;
- AddScore(dpy, window, cmap, xlim, ylim, 100 * level);
- DrawCities(dpy, window, cmap, xlim, ylim);
- XSync(dpy, False);
- screenhack_handle_events(dpy);
- usleep(kCityPause);
- }
- }
- }
- else {
- /* we're dead */
- screenhack_handle_events(dpy);
- sleep(3);
- screenhack_handle_events(dpy);
- /* start new */
- gamez++;
- Improve();
- for (i=0;i<kNumCities;i++)
- city[i].alive = 1;
- level = 0;
- loop = 1;
- score = 0;
- nextBonus = kFirstBonus;
- numBonus = 0;
- DrawCities(dpy, window, cmap, xlim, ylim);
- }
- }
-
- /* do free city part */
- if (freecity && sumlive < 5) {
- int ncnt = random() % (5 - sumlive) + 1;
- for (i=0;i<kNumCities;i++)
- if (!city[i].alive)
- if (!--ncnt)
- city[i].alive = 1;
- strcpy(buf, "Bonus City");
- width = XTextWidth(font, buf, strlen(buf));
- XDrawString(dpy, window, level_gc, xlim / 2 - width / 2, ylim / 4, buf, strlen(buf));
- DrawCities(dpy, window, cmap, xlim, ylim);
- XSync(dpy, False);
- screenhack_handle_events(dpy);
- sleep(1);
- }
-
- XFillRectangle(dpy, window, erase_gc,
- 0, 0, xlim, ylim - 100);
-
- if (!bround)
- level++;
- if (level == 1) {
- nextBonus = kFirstBonus;
- }
-
- if (level > 3 && (level % 5 == 1)) {
- if (bround) {
- bround = 0;
- DrawCities(dpy, window, cmap, xlim, ylim);
- }
- else {
- /* bonus round */
- bround = 1;
- levMissiles = 20 + level * 10;
- levFreq = 10;
- for (i=0;i<kNumCities;i++)
- blive[i] = city[i].alive;
- sprintf(buf, "Bonus Round");
- width = XTextWidth(font, buf, strlen(buf));
- XDrawString(dpy, window, level_gc, xlim / 2 - width / 2, ylim / 2 - font_height(font) / 2, buf, strlen(buf));
- XSync(dpy, False);
- screenhack_handle_events(dpy);
- sleep(1);
- XFillRectangle(dpy, window, erase_gc,
- 0, 0, xlim, ylim - 100);
- }
- }
-
- END_LEVEL: ;
-
- if (!bround) {
- levMissiles = 5 + level * 3;
- if (level > 5)
- levMissiles += level * 5;
- /* levMissiles = 2; */
- levFreq = 120 - level * 5;
- if (levFreq < 30)
- levFreq = 30;
- }
-
- /* ready to fire */
- lastLaser = 0;
-}
-
-static void penetrate(Display *dpy, Window window, Colormap cmap)
-{
- XWindowAttributes xgwa;
- static int xlim, ylim;
-
- XGetWindowAttributes(dpy, window, &xgwa);
- xlim = xgwa.width;
- ylim = xgwa.height;
-
- /* see if just started */
- if (loop == 0) {
- if (smart) {
- choosypersen = econpersen = carefulpersen = 100;
- lrate = kMinRate; aim = 1;
- }
- NewLevel(dpy, window, cmap, xlim, ylim);
- DrawScore(dpy, window, cmap, xlim, ylim);
- }
-
- loop++;
-
- if (levMissiles == 0) {
- /* see if anything's still on the screen, to know when to end level */
- int i;
- for (i=0;i<kMaxMissiles;i++)
- if (missile[i].alive)
- goto END_CHECK;
- for (i=0;i<kMaxBooms;i++)
- if (boom[i].alive)
- goto END_CHECK;
- for (i=0;i<kMaxLasers;i++)
- if (laser[i].alive)
- goto END_CHECK;
- /* okay, nothing's alive, start end of level countdown */
- screenhack_handle_events(dpy);
- sleep(kLevelPause);
- NewLevel(dpy, window, cmap, xlim, ylim);
- return;
- END_CHECK: ;
- }
- else if ((random() % levFreq) == 0) {
- launch(xlim, ylim, dpy, cmap, -1);
- levMissiles--;
- }
-
- if (loop - lastLaser >= lrate) {
- if (fire(xlim, ylim, dpy, window, cmap))
- lastLaser = loop;
- }
-
- XSync(dpy, False);
- screenhack_handle_events(dpy);
- if (kSleepTime)
- usleep(kSleepTime);
-
- if ((loop & 7) == 0)
- DrawCities(dpy, window, cmap, xlim, ylim);
- LoopMissiles(dpy, window, cmap, xlim, ylim);
- LoopLasers(dpy, window, cmap, xlim, ylim);
- LoopBooms(dpy, window, cmap, xlim, ylim);
-}
-
-char *progclass = "Penetrate";
-
-char *defaults [] = {
- ".background: black",
- ".foreground: white",
- "*bgrowth: 5",
- "*lrate: 80",
- "*geometry: 800x500",
- 0
-};
-
-XrmOptionDescRec options [] = {
- { "-bgrowth", ".bgrowth", XrmoptionSepArg, 0 },
- { "-lrate", ".lrate", XrmoptionSepArg, 0 },
- {"-smart", ".smart", XrmoptionIsArg,0},
- { 0, 0, 0, 0 }
-};
-
-void
-screenhack (Display *dpy, Window window)
-{
- Colormap cmap = init_penetrate(dpy, window);
- while (1)
- penetrate(dpy, window, cmap);
-}