Berkeley copyright
[unix-history] / usr / src / games / trek / events.c
CommitLineData
b6f0a7e4
DF
1/*
2 * Copyright (c) 1980 Regents of the University of California.
e9fb6bea
KB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
d99e6414
KB
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
b6f0a7e4
DF
16 */
17
bab4d182 18#ifndef lint
d99e6414 19static char sccsid[] = "@(#)events.c 5.3 (Berkeley) %G%";
e9fb6bea 20#endif /* not lint */
bab4d182
KM
21
22# include "trek.h"
23
24/*
25** CAUSE TIME TO ELAPSE
26**
27** This routine does a hell of a lot. It elapses time, eats up
28** energy, regenerates energy, processes any events that occur,
29** and so on.
30*/
31
32
33events(warp)
34int warp; /* set if called in a time warp */
35{
36 register int i;
37 int j;
38 struct kling *k;
39 double rtime;
40 double xdate;
41 double idate;
06d69904 42 struct event *ev, *xsched(), *schedule();
bab4d182
KM
43 int ix, iy;
44 register struct quad *q;
45 register struct event *e;
46 int evnum;
47 int restcancel;
48
49 /* if nothing happened, just allow for any Klingons killed */
50 if (Move.time <= 0.0)
51 {
52 Now.time = Now.resource / Now.klings;
53 return (0);
54 }
55
56 /* indicate that the cloaking device is now working */
57 Ship.cloakgood = 1;
58
59 /* idate is the initial date */
60 idate = Now.date;
61
62 /* schedule attacks if resting too long */
63 if (Move.time > 0.5 && Move.resting)
64 schedule(E_ATTACK, 0.5, 0, 0, 0);
65
66 /* scan the event list */
67 while (1)
68 {
69 restcancel = 0;
70 evnum = -1;
71 /* xdate is the date of the current event */
72 xdate = idate + Move.time;
73
74 /* find the first event that has happened */
75 for (i = 0; i < MAXEVENTS; i++)
76 {
77 e = &Event[i];
78 if (e->evcode == 0 || (e->evcode & E_GHOST))
79 continue;
80 if (e->date < xdate)
81 {
82 xdate = e->date;
83 ev = e;
84 evnum = i;
85 }
86 }
87 e = ev;
88
89 /* find the time between events */
90 rtime = xdate - Now.date;
91
92 /* decrement the magic "Federation Resources" pseudo-variable */
06d69904 93 Now.resource -= Now.klings * rtime;
bab4d182
KM
94 /* and recompute the time left */
95 Now.time = Now.resource / Now.klings;
96
97 /* move us up to the next date */
98 Now.date = xdate;
99
100 /* check for out of time */
101 if (Now.time <= 0.0)
102 lose(L_NOTIME);
103# ifdef xTRACE
104 if (evnum >= 0 && Trace)
105 printf("xdate = %.2f, evcode %d params %d %d %d\n",
106 xdate, e->evcode, e->x, e->y, e->systemname);
107# endif
108
109 /* if evnum < 0, no events occurred */
110 if (evnum < 0)
111 break;
112
113 /* otherwise one did. Find out what it is */
114 switch (e->evcode & E_EVENT)
115 {
116
117 case E_SNOVA: /* supernova */
118 /* cause the supernova to happen */
119 snova(-1);
120 /* and schedule the next one */
121 xresched(e, E_SNOVA, 1);
122 break;
123
124 case E_LRTB: /* long range tractor beam */
125 /* schedule the next one */
126 xresched(e, E_LRTB, Now.klings);
127 /* LRTB cannot occur if we are docked */
128 if (Ship.cond != DOCKED)
129 {
130 /* pick a new quadrant */
131 i = ranf(Now.klings) + 1;
132 for (ix = 0; ix < NQUADS; ix++)
133 {
134 for (iy = 0; iy < NQUADS; iy++)
135 {
136 q = &Quad[ix][iy];
137 if (q->stars >= 0)
06d69904 138 if ((i -= q->klings) <= 0)
bab4d182
KM
139 break;
140 }
141 if (i <= 0)
142 break;
143 }
144
145 /* test for LRTB to same quadrant */
146 if (Ship.quadx == ix && Ship.quady == iy)
147 break;
148
149 /* nope, dump him in the new quadrant */
150 Ship.quadx = ix;
151 Ship.quady = iy;
152 printf("\n%s caught in long range tractor beam\n", Ship.shipname);
153 printf("*** Pulled to quadrant %d,%d\n", Ship.quadx, Ship.quady);
154 Ship.sectx = ranf(NSECTS);
155 Ship.secty = ranf(NSECTS);
156 initquad(0);
157 /* truncate the move time */
158 Move.time = xdate - idate;
159 }
160 break;
161
162 case E_KATSB: /* Klingon attacks starbase */
163 /* if out of bases, forget it */
164 if (Now.bases <= 0)
165 {
166 unschedule(e);
167 break;
168 }
169
170 /* check for starbase and Klingons in same quadrant */
171 for (i = 0; i < Now.bases; i++)
172 {
173 ix = Now.base[i].x;
174 iy = Now.base[i].y;
175 /* see if a Klingon exists in this quadrant */
176 q = &Quad[ix][iy];
177 if (q->klings <= 0)
178 continue;
179
180 /* see if already distressed */
181 for (j = 0; j < MAXEVENTS; j++)
182 {
183 e = &Event[j];
184 if ((e->evcode & E_EVENT) != E_KDESB)
185 continue;
186 if (e->x == ix && e->y == iy)
187 break;
188 }
189 if (j < MAXEVENTS)
190 continue;
191
192 /* got a potential attack */
193 break;
194 }
195 e = ev;
196 if (i >= Now.bases)
197 {
198 /* not now; wait a while and see if some Klingons move in */
199 reschedule(e, 0.5 + 3.0 * franf());
200 break;
201 }
202 /* schedule a new attack, and a destruction of the base */
203 xresched(e, E_KATSB, 1);
204 e = xsched(E_KDESB, 1, ix, iy, 0);
205
206 /* report it if we can */
207 if (!damaged(SSRADIO))
208 {
209 printf("\nUhura: Captain, we have recieved a distress signal\n");
210 printf(" from the starbase in quadrant %d,%d.\n",
211 ix, iy);
212 restcancel++;
213 }
214 else
215 /* SSRADIO out, make it so we can't see the distress call */
216 /* but it's still there!!! */
06d69904 217 e->evcode |= E_HIDDEN;
bab4d182
KM
218 break;
219
220 case E_KDESB: /* Klingon destroys starbase */
221 unschedule(e);
222 q = &Quad[e->x][e->y];
223 /* if the base has mysteriously gone away, or if the Klingon
224 got tired and went home, ignore this event */
225 if (q->bases <=0 || q->klings <= 0)
226 break;
227 /* are we in the same quadrant? */
228 if (e->x == Ship.quadx && e->y == Ship.quady)
229 {
230 /* yep, kill one in this quadrant */
231 printf("\nSpock: ");
232 killb(Ship.quadx, Ship.quady);
233 }
234 else
235 /* kill one in some other quadrant */
236 killb(e->x, e->y);
237 break;
238
239 case E_ISSUE: /* issue a distress call */
240 xresched(e, E_ISSUE, 1);
241 /* if we already have too many, throw this one away */
242 if (Ship.distressed >= MAXDISTR)
243 break;
244 /* try a whole bunch of times to find something suitable */
245 for (i = 0; i < 100; i++)
246 {
247 ix = ranf(NQUADS);
248 iy = ranf(NQUADS);
249 q = &Quad[ix][iy];
250 /* need a quadrant which is not the current one,
251 which has some stars which are inhabited and
252 not already under attack, which is not
253 supernova'ed, and which has some Klingons in it */
254 if (!((ix == Ship.quadx && iy == Ship.quady) || q->stars < 0 ||
06d69904
KL
255 (q->qsystemname & Q_DISTRESSED) ||
256 (q->qsystemname & Q_SYSTEM) == 0 || q->klings <= 0))
bab4d182
KM
257 break;
258 }
259 if (i >= 100)
260 /* can't seem to find one; ignore this call */
261 break;
262
263 /* got one!! Schedule its enslavement */
06d69904
KL
264 Ship.distressed++;
265 e = xsched(E_ENSLV, 1, ix, iy, q->qsystemname);
266 q->qsystemname = (e - Event) | Q_DISTRESSED;
bab4d182
KM
267
268 /* tell the captain about it if we can */
269 if (!damaged(SSRADIO))
270 {
271 printf("\nUhura: Captain, starsystem %s in quadrant %d,%d is under attack\n",
272 Systemname[e->systemname], ix, iy);
273 restcancel++;
274 }
275 else
276 /* if we can't tell him, make it invisible */
06d69904 277 e->evcode |= E_HIDDEN;
bab4d182
KM
278 break;
279
280 case E_ENSLV: /* starsystem is enslaved */
281 unschedule(e);
282 /* see if current distress call still active */
283 q = &Quad[e->x][e->y];
284 if (q->klings <= 0)
285 {
286 /* no Klingons, clean up */
287 /* restore the system name */
06d69904 288 q->qsystemname = e->systemname;
bab4d182
KM
289 break;
290 }
291
292 /* play stork and schedule the first baby */
293 e = schedule(E_REPRO, Param.eventdly[E_REPRO] * franf(), e->x, e->y, e->systemname);
294
295 /* report the disaster if we can */
296 if (!damaged(SSRADIO))
297 {
298 printf("\nUhura: We've lost contact with starsystem %s\n",
299 Systemname[e->systemname]);
300 printf(" in quadrant %d,%d.\n",
301 e->x, e->y);
302 }
303 else
06d69904 304 e->evcode |= E_HIDDEN;
bab4d182
KM
305 break;
306
307 case E_REPRO: /* Klingon reproduces */
308 /* see if distress call is still active */
309 q = &Quad[e->x][e->y];
310 if (q->klings <= 0)
311 {
312 unschedule(e);
06d69904 313 q->qsystemname = e->systemname;
bab4d182
KM
314 break;
315 }
316 xresched(e, E_REPRO, 1);
317 /* reproduce one Klingon */
318 ix = e->x;
319 iy = e->y;
320 if (Now.klings == 127)
321 break; /* full right now */
322 if (q->klings >= MAXKLQUAD)
323 {
324 /* this quadrant not ok, pick an adjacent one */
325 for (i = ix - 1; i <= ix + 1; i++)
326 {
327 if (i < 0 || i >= NQUADS)
328 continue;
329 for (j = iy - 1; j <= iy + 1; j++)
330 {
331 if (j < 0 || j >= NQUADS)
332 continue;
333 q = &Quad[i][j];
334 /* check for this quad ok (not full & no snova) */
335 if (q->klings >= MAXKLQUAD || q->stars < 0)
336 continue;
337 break;
338 }
339 if (j <= iy + 1)
340 break;
341 }
342 if (j > iy + 1)
343 /* cannot create another yet */
344 break;
345 ix = i;
346 iy = j;
347 }
348 /* deliver the child */
06d69904
KL
349 q->klings++;
350 Now.klings++;
bab4d182
KM
351 if (ix == Ship.quadx && iy == Ship.quady)
352 {
353 /* we must position Klingon */
354 sector(&ix, &iy);
355 Sect[ix][iy] = KLINGON;
356 k = &Etc.klingon[Etc.nkling++];
357 k->x = ix;
358 k->y = iy;
359 k->power = Param.klingpwr;
360 k->srndreq = 0;
361 compkldist(Etc.klingon[0].dist == Etc.klingon[0].avgdist ? 0 : 1);
362 }
363
364 /* recompute time left */
365 Now.time = Now.resource / Now.klings;
366 break;
367
368 case E_SNAP: /* take a snapshot of the galaxy */
369 xresched(e, E_SNAP, 1);
06d69904
KL
370 i = (int) Etc.snapshot;
371 i = bmove(Quad, i, sizeof (Quad));
372 i = bmove(Event, i, sizeof (Event));
9623cd28 373 i = bmove(&Now, i, sizeof (Now));
bab4d182
KM
374 Game.snap = 1;
375 break;
376
377 case E_ATTACK: /* Klingons attack during rest period */
378 if (!Move.resting)
379 {
380 unschedule(e);
381 break;
382 }
383 attack(1);
384 reschedule(e, 0.5);
385 break;
386
387 case E_FIXDV:
388 i = e->systemname;
389 unschedule(e);
390
391 /* de-damage the device */
392 printf("%s reports repair work on the %s finished.\n",
393 Device[i].person, Device[i].name);
394
395 /* handle special processing upon fix */
396 switch (i)
397 {
398
399 case LIFESUP:
400 Ship.reserves = Param.reserves;
401 break;
402
403 case SINS:
404 if (Ship.cond == DOCKED)
405 break;
406 printf("Spock has tried to recalibrate your Space Internal Navigation System,\n");
407 printf(" but he has no standard base to calibrate to. Suggest you get\n");
408 printf(" to a starbase immediately so that you can properly recalibrate.\n");
409 Ship.sinsbad = 1;
410 break;
411
412 case SSRADIO:
413 restcancel = dumpssradio();
414 break;
415 }
416 break;
417
418 default:
419 break;
420 }
421
422 if (restcancel && Move.resting && getynpar("Spock: Shall we cancel our rest period"))
423 Move.time = xdate - idate;
424
425 }
426
427 /* unschedule an attack during a rest period */
428 if (e = Now.eventptr[E_ATTACK])
429 unschedule(e);
430
431 if (!warp)
432 {
433 /* eat up energy if cloaked */
434 if (Ship.cloaked)
06d69904 435 Ship.energy -= Param.cloakenergy * Move.time;
bab4d182
KM
436
437 /* regenerate resources */
438 rtime = 1.0 - exp(-Param.regenfac * Move.time);
06d69904
KL
439 Ship.shield += (Param.shield - Ship.shield) * rtime;
440 Ship.energy += (Param.energy - Ship.energy) * rtime;
bab4d182
KM
441
442 /* decrement life support reserves */
443 if (damaged(LIFESUP) && Ship.cond != DOCKED)
06d69904 444 Ship.reserves -= Move.time;
bab4d182
KM
445 }
446 return (0);
447}