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: 7: #ifndef lint 8: static char sccsid[] = "@(#)events.c 5.1 (Berkeley) 5/30/85"; 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: 22: events(warp) 23: int 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; 31: struct event *ev, *xsched(), *schedule(); 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 */ 82: Now.resource -= Now.klings * rtime; 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) 127: if ((i -= q->klings) <= 0) 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!!! */ 206: e->evcode |= E_HIDDEN; 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 || 244: (q->qsystemname & Q_DISTRESSED) || 245: (q->qsystemname & Q_SYSTEM) == 0 || q->klings <= 0)) 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 */ 253: Ship.distressed++; 254: e = xsched(E_ENSLV, 1, ix, iy, q->qsystemname); 255: q->qsystemname = (e - Event) | Q_DISTRESSED; 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 */ 266: e->evcode |= E_HIDDEN; 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 */ 277: q->qsystemname = e->systemname; 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 293: e->evcode |= E_HIDDEN; 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); 302: q->qsystemname = e->systemname; 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 */ 338: q->klings++; 339: Now.klings++; 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); 359: i = (int) Etc.snapshot; 360: i = bmove(Quad, i, sizeof (Quad)); 361: i = bmove(Event, i, sizeof (Event)); 362: i = bmove(&Now, i, sizeof (Now)); 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) 424: Ship.energy -= Param.cloakenergy * Move.time; 425: 426: /* regenerate resources */ 427: rtime = 1.0 - exp(-Param.regenfac * Move.time); 428: Ship.shield += (Param.shield - Ship.shield) * rtime; 429: Ship.energy += (Param.energy - Ship.energy) * rtime; 430: 431: /* decrement life support reserves */ 432: if (damaged(LIFESUP) && Ship.cond != DOCKED) 433: Ship.reserves -= Move.time; 434: } 435: return (0); 436: }