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