|
|
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.