|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
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.
16: */
17:
18: #ifndef lint
19: static char sccsid[] = "@(#)events.c 5.3 (Berkeley) 6/18/88";
20: #endif /* not lint */
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:
33: events(warp)
34: int 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;
42: struct event *ev, *xsched(), *schedule();
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 */
93: Now.resource -= Now.klings * rtime;
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)
138: if ((i -= q->klings) <= 0)
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!!! */
217: e->evcode |= E_HIDDEN;
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 ||
255: (q->qsystemname & Q_DISTRESSED) ||
256: (q->qsystemname & Q_SYSTEM) == 0 || q->klings <= 0))
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 */
264: Ship.distressed++;
265: e = xsched(E_ENSLV, 1, ix, iy, q->qsystemname);
266: q->qsystemname = (e - Event) | Q_DISTRESSED;
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 */
277: e->evcode |= E_HIDDEN;
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 */
288: q->qsystemname = e->systemname;
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
304: e->evcode |= E_HIDDEN;
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);
313: q->qsystemname = e->systemname;
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 */
349: q->klings++;
350: Now.klings++;
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);
370: i = (int) Etc.snapshot;
371: i = bmove(Quad, i, sizeof (Quad));
372: i = bmove(Event, i, sizeof (Event));
373: i = bmove(&Now, i, sizeof (Now));
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)
435: Ship.energy -= Param.cloakenergy * Move.time;
436:
437: /* regenerate resources */
438: rtime = 1.0 - exp(-Param.regenfac * Move.time);
439: Ship.shield += (Param.shield - Ship.shield) * rtime;
440: Ship.energy += (Param.energy - Ship.energy) * rtime;
441:
442: /* decrement life support reserves */
443: if (damaged(LIFESUP) && Ship.cond != DOCKED)
444: Ship.reserves -= Move.time;
445: }
446: return (0);
447: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.