Sync usage with man page.
[netbsd-mini2440.git] / games / trek / events.c
bloba56ad310539199fafb08d9e4845741938d5bc292
1 /* $NetBSD: events.c,v 1.10 2009/05/24 21:44:56 dholland Exp $ */
3 /*
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)events.c 8.1 (Berkeley) 5/31/93";
36 #else
37 __RCSID("$NetBSD: events.c,v 1.10 2009/05/24 21:44:56 dholland Exp $");
38 #endif
39 #endif /* not lint */
41 #include <stdio.h>
42 #include <string.h>
43 #include <math.h>
44 #include "getpar.h"
45 #include "trek.h"
48 ** CAUSE TIME TO ELAPSE
50 ** This routine does a hell of a lot. It elapses time, eats up
51 ** energy, regenerates energy, processes any events that occur,
52 ** and so on.
54 ** 'timewarp' is set if called in a time warp.
57 int
58 events(int timewarp)
60 int i;
61 char *p;
62 int j = 0;
63 struct kling *k;
64 double rtime;
65 double xdate;
66 double idate;
67 struct event *ev = NULL;
68 int ix, iy;
69 struct quad *q;
70 struct event *e;
71 int evnum;
72 int restcancel;
74 /* if nothing happened, just allow for any Klingons killed */
75 if (Move.time <= 0.0) {
76 Now.time = Now.resource / Now.klings;
77 return (0);
80 /* indicate that the cloaking device is now working */
81 Ship.cloakgood = 1;
83 /* idate is the initial date */
84 idate = Now.date;
86 /* schedule attacks if resting too long */
87 if (Move.time > 0.5 && Move.resting)
88 schedule(E_ATTACK, 0.5, 0, 0, 0);
90 /* scan the event list */
91 while (1) {
92 restcancel = 0;
93 evnum = -1;
94 /* xdate is the date of the current event */
95 xdate = idate + Move.time;
97 /* find the first event that has happened */
98 for (i = 0; i < MAXEVENTS; i++) {
99 e = &Event[i];
100 if (e->evcode == 0 || (e->evcode & E_GHOST))
101 continue;
102 if (e->date < xdate) {
103 xdate = e->date;
104 ev = e;
105 evnum = i;
108 e = ev;
110 /* find the time between events */
111 rtime = xdate - Now.date;
113 /* decrement the magic "Federation Resources" pseudo-variable */
114 Now.resource -= Now.klings * rtime;
115 /* and recompute the time left */
116 Now.time = Now.resource / Now.klings;
118 /* move us up to the next date */
119 Now.date = xdate;
121 /* check for out of time */
122 if (Now.time <= 0.0)
123 lose(L_NOTIME);
124 #ifdef xTRACE
125 if (evnum >= 0 && Trace)
126 printf("xdate = %.2f, evcode %d params %d %d %d\n",
127 xdate, e->evcode, e->x, e->y, e->systemname);
128 #endif
130 /* if evnum < 0, no events occurred */
131 if (evnum < 0)
132 break;
134 /* otherwise one did. Find out what it is */
135 switch (e->evcode & E_EVENT) {
137 case E_SNOVA: /* supernova */
138 /* cause the supernova to happen */
139 snova(-1, 0);
140 /* and schedule the next one */
141 xresched(e, E_SNOVA, 1);
142 break;
144 case E_LRTB: /* long range tractor beam */
145 /* schedule the next one */
146 xresched(e, E_LRTB, Now.klings);
147 /* LRTB cannot occur if we are docked */
148 if (Ship.cond != DOCKED) {
149 /* pick a new quadrant */
150 i = ranf(Now.klings) + 1;
151 for (ix = 0; ix < NQUADS; ix++) {
152 for (iy = 0; iy < NQUADS; iy++) {
153 q = &Quad[ix][iy];
154 if (q->stars >= 0)
155 if ((i -= q->klings)
156 <= 0)
157 break;
159 if (i <= 0)
160 break;
163 /* test for LRTB to same quadrant */
164 if (Ship.quadx == ix && Ship.quady == iy)
165 break;
167 /* nope, dump him in the new quadrant */
168 Ship.quadx = ix;
169 Ship.quady = iy;
170 printf("\n%s caught in long range tractor "
171 "beam\n",
172 Ship.shipname);
173 printf("*** Pulled to quadrant %d,%d\n",
174 Ship.quadx, Ship.quady);
175 Ship.sectx = ranf(NSECTS);
176 Ship.secty = ranf(NSECTS);
177 initquad(0);
178 /* truncate the move time */
179 Move.time = xdate - idate;
181 break;
183 case E_KATSB: /* Klingon attacks starbase */
184 /* if out of bases, forget it */
185 if (Now.bases <= 0) {
186 unschedule(e);
187 break;
190 /* check for starbase and Klingons in same quadrant */
191 for (i = 0; i < Now.bases; i++) {
192 ix = Now.base[i].x;
193 iy = Now.base[i].y;
194 /* see if a Klingon exists in this quadrant */
195 q = &Quad[ix][iy];
196 if (q->klings <= 0)
197 continue;
199 /* see if already distressed */
200 for (j = 0; j < MAXEVENTS; j++) {
201 e = &Event[j];
202 if ((e->evcode & E_EVENT) != E_KDESB)
203 continue;
204 if (e->x == ix && e->y == iy)
205 break;
207 if (j < MAXEVENTS)
208 continue;
210 /* got a potential attack */
211 break;
213 e = ev;
214 if (i >= Now.bases) {
216 * not now; wait a while and see if
217 * some Klingons move in
219 reschedule(e, 0.5 + 3.0 * franf());
220 break;
223 * schedule a new attack, and a destruction of
224 * the base
226 xresched(e, E_KATSB, 1);
227 e = xsched(E_KDESB, 1, ix, iy, 0);
229 /* report it if we can */
230 if (!damaged(SSRADIO)) {
231 printf("\nUhura: Captain, we have received a "
232 "distress signal\n");
233 printf(" from the starbase in quadrant "
234 "%d,%d.\n",
235 ix, iy);
236 restcancel++;
237 } else {
239 * SSRADIO out, make it so we can't see the
240 * distress call but it's still there!!!
242 e->evcode |= E_HIDDEN;
244 break;
246 case E_KDESB: /* Klingon destroys starbase */
247 unschedule(e);
248 q = &Quad[e->x][e->y];
250 * if the base has mysteriously gone away, or if the
251 * Klingon got tired and went home, ignore this event
253 if (q->bases <=0 || q->klings <= 0)
254 break;
255 /* are we in the same quadrant? */
256 if (e->x == Ship.quadx && e->y == Ship.quady) {
257 /* yep, kill one in this quadrant */
258 printf("\nSpock: ");
259 killb(Ship.quadx, Ship.quady);
260 } else {
261 /* kill one in some other quadrant */
262 killb(e->x, e->y);
264 break;
266 case E_ISSUE: /* issue a distress call */
267 xresched(e, E_ISSUE, 1);
268 /* if we already have too many, throw this one away */
269 if (Ship.distressed >= MAXDISTR)
270 break;
271 /* try a bunch of times to find something suitable */
272 for (i = 0; i < 100; i++) {
273 ix = ranf(NQUADS);
274 iy = ranf(NQUADS);
275 q = &Quad[ix][iy];
277 * need a quadrant which is not the current
278 * one, which has some inhabited stars which
279 * are not already under attack, which is not
280 * supernova'ed, and which has some Klingons
281 * in it
283 if (!((ix == Ship.quadx && iy == Ship.quady) ||
284 q->stars < 0 ||
285 (q->qsystemname & Q_DISTRESSED) ||
286 (q->qsystemname & Q_SYSTEM) == 0 ||
287 q->klings <= 0))
288 break;
290 if (i >= 100)
291 /* can't seem to find one; ignore this call */
292 break;
294 /* got one!! Schedule its enslavement */
295 Ship.distressed++;
296 e = xsched(E_ENSLV, 1, ix, iy, q->qsystemname);
297 q->qsystemname = (e - Event) | Q_DISTRESSED;
299 /* tell the captain about it if we can */
300 if (!damaged(SSRADIO)) {
301 printf("\nUhura: Captain, starsystem %s in "
302 "quadrant %d,%d is under attack\n",
303 Systemname[e->systemname], ix, iy);
304 restcancel++;
305 } else {
306 /* if we can't tell him, make it invisible */
307 e->evcode |= E_HIDDEN;
309 break;
311 case E_ENSLV: /* starsystem is enslaved */
312 unschedule(e);
313 /* see if current distress call still active */
314 q = &Quad[e->x][e->y];
315 if (q->klings <= 0) {
316 /* no Klingons, clean up */
317 /* restore the system name */
318 q->qsystemname = e->systemname;
319 break;
322 /* play stork and schedule the first baby */
323 e = schedule(E_REPRO, Param.eventdly[E_REPRO] * franf(),
324 e->x, e->y, e->systemname);
326 /* report the disaster if we can */
327 if (!damaged(SSRADIO)) {
328 printf("\nUhura: We've lost contact with "
329 "starsystem %s\n",
330 Systemname[e->systemname]);
331 printf(" in quadrant %d,%d.\n",
332 e->x, e->y);
333 } else
334 e->evcode |= E_HIDDEN;
335 break;
337 case E_REPRO: /* Klingon reproduces */
338 /* see if distress call is still active */
339 q = &Quad[e->x][e->y];
340 if (q->klings <= 0) {
341 unschedule(e);
342 q->qsystemname = e->systemname;
343 break;
345 xresched(e, E_REPRO, 1);
346 /* reproduce one Klingon */
347 ix = e->x;
348 iy = e->y;
349 if (Now.klings == 127) {
350 /* full right now */
351 break;
353 if (q->klings >= MAXKLQUAD) {
354 /* this quadrant not ok, pick an adjacent one */
355 for (i = ix - 1; i <= ix + 1; i++) {
356 if (i < 0 || i >= NQUADS)
357 continue;
358 for (j = iy - 1; j <= iy + 1; j++) {
359 if (j < 0 || j >= NQUADS)
360 continue;
361 q = &Quad[i][j];
363 * check for this quad ok (not
364 * full & no snova)
366 if (q->klings >= MAXKLQUAD ||
367 q->stars < 0)
368 continue;
369 break;
371 if (j <= iy + 1)
372 break;
374 if (j > iy + 1)
375 /* cannot create another yet */
376 break;
377 ix = i;
378 iy = j;
380 /* deliver the child */
381 q->klings++;
382 Now.klings++;
383 if (ix == Ship.quadx && iy == Ship.quady) {
384 /* we must position Klingon */
385 sector(&ix, &iy);
386 Sect[ix][iy] = KLINGON;
387 k = &Etc.klingon[Etc.nkling++];
388 k->x = ix;
389 k->y = iy;
390 k->power = Param.klingpwr;
391 k->srndreq = 0;
392 compkldist(Etc.klingon[0].dist ==
393 Etc.klingon[0].avgdist ? 0 : 1);
396 /* recompute time left */
397 Now.time = Now.resource / Now.klings;
398 break;
400 case E_SNAP: /* take a snapshot of the galaxy */
401 xresched(e, E_SNAP, 1);
402 p = (char *) Etc.snapshot;
403 memcpy(p, Quad, sizeof (Quad));
404 p += sizeof(Quad);
405 memcpy(p, Event, sizeof (Event));
406 p += sizeof(Event);
407 memcpy(p, &Now, sizeof (Now));
408 Game.snap = 1;
409 break;
411 case E_ATTACK: /* Klingons attack during rest period */
412 if (!Move.resting) {
413 unschedule(e);
414 break;
416 attack(1);
417 reschedule(e, 0.5);
418 break;
420 case E_FIXDV:
421 i = e->systemname;
422 unschedule(e);
424 /* de-damage the device */
425 printf("%s reports repair work on the %s finished.\n",
426 Device[i].person, Device[i].name);
428 /* handle special processing upon fix */
429 switch (i) {
431 case LIFESUP:
432 Ship.reserves = Param.reserves;
433 break;
435 case SINS:
436 if (Ship.cond == DOCKED)
437 break;
438 printf("Spock has tried to recalibrate your "
439 "Space Internal Navigation System,\n");
440 printf(" but he has no standard base to "
441 "calibrate to. Suggest you get\n");
442 printf(" to a starbase immediately so that "
443 "you can properly recalibrate.\n");
444 Ship.sinsbad = 1;
445 break;
447 case SSRADIO:
448 restcancel = dumpssradio();
449 break;
451 break;
453 default:
454 break;
457 if (restcancel && Move.resting &&
458 getynpar("Spock: Shall we cancel our rest period"))
459 Move.time = xdate - idate;
463 /* unschedule an attack during a rest period */
464 if ((e = Now.eventptr[E_ATTACK]) != NULL)
465 unschedule(e);
467 if (!timewarp) {
468 /* eat up energy if cloaked */
469 if (Ship.cloaked)
470 Ship.energy -= Param.cloakenergy * Move.time;
472 /* regenerate resources */
473 rtime = 1.0 - exp(-Param.regenfac * Move.time);
474 Ship.shield += (Param.shield - Ship.shield) * rtime;
475 Ship.energy += (Param.energy - Ship.energy) * rtime;
477 /* decrement life support reserves */
478 if (damaged(LIFESUP) && Ship.cond != DOCKED)
479 Ship.reserves -= Move.time;
481 return (0);