From 77e3814f0c0e3dea4d0032e25666f77e6f83bfff Mon Sep 17 00:00:00 2001 From: cgd Date: Sun, 21 Mar 1993 09:45:37 +0000 Subject: initial import of 386bsd-0.1 sources --- trek/events.c | 463 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 463 insertions(+) create mode 100644 trek/events.c (limited to 'trek/events.c') diff --git a/trek/events.c b/trek/events.c new file mode 100644 index 00000000..4ed6d982 --- /dev/null +++ b/trek/events.c @@ -0,0 +1,463 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)events.c 5.4 (Berkeley) 6/1/90"; +#endif /* not lint */ + +# include "trek.h" + +/* +** CAUSE TIME TO ELAPSE +** +** This routine does a hell of a lot. It elapses time, eats up +** energy, regenerates energy, processes any events that occur, +** and so on. +*/ + + +events(warp) +int warp; /* set if called in a time warp */ +{ + register int i; + int j; + struct kling *k; + double rtime; + double xdate; + double idate; + struct event *ev, *xsched(), *schedule(); + int ix, iy; + register struct quad *q; + register struct event *e; + int evnum; + int restcancel; + + /* if nothing happened, just allow for any Klingons killed */ + if (Move.time <= 0.0) + { + Now.time = Now.resource / Now.klings; + return (0); + } + + /* indicate that the cloaking device is now working */ + Ship.cloakgood = 1; + + /* idate is the initial date */ + idate = Now.date; + + /* schedule attacks if resting too long */ + if (Move.time > 0.5 && Move.resting) + schedule(E_ATTACK, 0.5, 0, 0, 0); + + /* scan the event list */ + while (1) + { + restcancel = 0; + evnum = -1; + /* xdate is the date of the current event */ + xdate = idate + Move.time; + + /* find the first event that has happened */ + for (i = 0; i < MAXEVENTS; i++) + { + e = &Event[i]; + if (e->evcode == 0 || (e->evcode & E_GHOST)) + continue; + if (e->date < xdate) + { + xdate = e->date; + ev = e; + evnum = i; + } + } + e = ev; + + /* find the time between events */ + rtime = xdate - Now.date; + + /* decrement the magic "Federation Resources" pseudo-variable */ + Now.resource -= Now.klings * rtime; + /* and recompute the time left */ + Now.time = Now.resource / Now.klings; + + /* move us up to the next date */ + Now.date = xdate; + + /* check for out of time */ + if (Now.time <= 0.0) + lose(L_NOTIME); +# ifdef xTRACE + if (evnum >= 0 && Trace) + printf("xdate = %.2f, evcode %d params %d %d %d\n", + xdate, e->evcode, e->x, e->y, e->systemname); +# endif + + /* if evnum < 0, no events occurred */ + if (evnum < 0) + break; + + /* otherwise one did. Find out what it is */ + switch (e->evcode & E_EVENT) + { + + case E_SNOVA: /* supernova */ + /* cause the supernova to happen */ + snova(-1); + /* and schedule the next one */ + xresched(e, E_SNOVA, 1); + break; + + case E_LRTB: /* long range tractor beam */ + /* schedule the next one */ + xresched(e, E_LRTB, Now.klings); + /* LRTB cannot occur if we are docked */ + if (Ship.cond != DOCKED) + { + /* pick a new quadrant */ + i = ranf(Now.klings) + 1; + for (ix = 0; ix < NQUADS; ix++) + { + for (iy = 0; iy < NQUADS; iy++) + { + q = &Quad[ix][iy]; + if (q->stars >= 0) + if ((i -= q->klings) <= 0) + break; + } + if (i <= 0) + break; + } + + /* test for LRTB to same quadrant */ + if (Ship.quadx == ix && Ship.quady == iy) + break; + + /* nope, dump him in the new quadrant */ + Ship.quadx = ix; + Ship.quady = iy; + printf("\n%s caught in long range tractor beam\n", Ship.shipname); + printf("*** Pulled to quadrant %d,%d\n", Ship.quadx, Ship.quady); + Ship.sectx = ranf(NSECTS); + Ship.secty = ranf(NSECTS); + initquad(0); + /* truncate the move time */ + Move.time = xdate - idate; + } + break; + + case E_KATSB: /* Klingon attacks starbase */ + /* if out of bases, forget it */ + if (Now.bases <= 0) + { + unschedule(e); + break; + } + + /* check for starbase and Klingons in same quadrant */ + for (i = 0; i < Now.bases; i++) + { + ix = Now.base[i].x; + iy = Now.base[i].y; + /* see if a Klingon exists in this quadrant */ + q = &Quad[ix][iy]; + if (q->klings <= 0) + continue; + + /* see if already distressed */ + for (j = 0; j < MAXEVENTS; j++) + { + e = &Event[j]; + if ((e->evcode & E_EVENT) != E_KDESB) + continue; + if (e->x == ix && e->y == iy) + break; + } + if (j < MAXEVENTS) + continue; + + /* got a potential attack */ + break; + } + e = ev; + if (i >= Now.bases) + { + /* not now; wait a while and see if some Klingons move in */ + reschedule(e, 0.5 + 3.0 * franf()); + break; + } + /* schedule a new attack, and a destruction of the base */ + xresched(e, E_KATSB, 1); + e = xsched(E_KDESB, 1, ix, iy, 0); + + /* report it if we can */ + if (!damaged(SSRADIO)) + { + printf("\nUhura: Captain, we have recieved a distress signal\n"); + printf(" from the starbase in quadrant %d,%d.\n", + ix, iy); + restcancel++; + } + else + /* SSRADIO out, make it so we can't see the distress call */ + /* but it's still there!!! */ + e->evcode |= E_HIDDEN; + break; + + case E_KDESB: /* Klingon destroys starbase */ + unschedule(e); + q = &Quad[e->x][e->y]; + /* if the base has mysteriously gone away, or if the Klingon + got tired and went home, ignore this event */ + if (q->bases <=0 || q->klings <= 0) + break; + /* are we in the same quadrant? */ + if (e->x == Ship.quadx && e->y == Ship.quady) + { + /* yep, kill one in this quadrant */ + printf("\nSpock: "); + killb(Ship.quadx, Ship.quady); + } + else + /* kill one in some other quadrant */ + killb(e->x, e->y); + break; + + case E_ISSUE: /* issue a distress call */ + xresched(e, E_ISSUE, 1); + /* if we already have too many, throw this one away */ + if (Ship.distressed >= MAXDISTR) + break; + /* try a whole bunch of times to find something suitable */ + for (i = 0; i < 100; i++) + { + ix = ranf(NQUADS); + iy = ranf(NQUADS); + q = &Quad[ix][iy]; + /* need a quadrant which is not the current one, + which has some stars which are inhabited and + not already under attack, which is not + supernova'ed, and which has some Klingons in it */ + if (!((ix == Ship.quadx && iy == Ship.quady) || q->stars < 0 || + (q->qsystemname & Q_DISTRESSED) || + (q->qsystemname & Q_SYSTEM) == 0 || q->klings <= 0)) + break; + } + if (i >= 100) + /* can't seem to find one; ignore this call */ + break; + + /* got one!! Schedule its enslavement */ + Ship.distressed++; + e = xsched(E_ENSLV, 1, ix, iy, q->qsystemname); + q->qsystemname = (e - Event) | Q_DISTRESSED; + + /* tell the captain about it if we can */ + if (!damaged(SSRADIO)) + { + printf("\nUhura: Captain, starsystem %s in quadrant %d,%d is under attack\n", + Systemname[e->systemname], ix, iy); + restcancel++; + } + else + /* if we can't tell him, make it invisible */ + e->evcode |= E_HIDDEN; + break; + + case E_ENSLV: /* starsystem is enslaved */ + unschedule(e); + /* see if current distress call still active */ + q = &Quad[e->x][e->y]; + if (q->klings <= 0) + { + /* no Klingons, clean up */ + /* restore the system name */ + q->qsystemname = e->systemname; + break; + } + + /* play stork and schedule the first baby */ + e = schedule(E_REPRO, Param.eventdly[E_REPRO] * franf(), e->x, e->y, e->systemname); + + /* report the disaster if we can */ + if (!damaged(SSRADIO)) + { + printf("\nUhura: We've lost contact with starsystem %s\n", + Systemname[e->systemname]); + printf(" in quadrant %d,%d.\n", + e->x, e->y); + } + else + e->evcode |= E_HIDDEN; + break; + + case E_REPRO: /* Klingon reproduces */ + /* see if distress call is still active */ + q = &Quad[e->x][e->y]; + if (q->klings <= 0) + { + unschedule(e); + q->qsystemname = e->systemname; + break; + } + xresched(e, E_REPRO, 1); + /* reproduce one Klingon */ + ix = e->x; + iy = e->y; + if (Now.klings == 127) + break; /* full right now */ + if (q->klings >= MAXKLQUAD) + { + /* this quadrant not ok, pick an adjacent one */ + for (i = ix - 1; i <= ix + 1; i++) + { + if (i < 0 || i >= NQUADS) + continue; + for (j = iy - 1; j <= iy + 1; j++) + { + if (j < 0 || j >= NQUADS) + continue; + q = &Quad[i][j]; + /* check for this quad ok (not full & no snova) */ + if (q->klings >= MAXKLQUAD || q->stars < 0) + continue; + break; + } + if (j <= iy + 1) + break; + } + if (j > iy + 1) + /* cannot create another yet */ + break; + ix = i; + iy = j; + } + /* deliver the child */ + q->klings++; + Now.klings++; + if (ix == Ship.quadx && iy == Ship.quady) + { + /* we must position Klingon */ + sector(&ix, &iy); + Sect[ix][iy] = KLINGON; + k = &Etc.klingon[Etc.nkling++]; + k->x = ix; + k->y = iy; + k->power = Param.klingpwr; + k->srndreq = 0; + compkldist(Etc.klingon[0].dist == Etc.klingon[0].avgdist ? 0 : 1); + } + + /* recompute time left */ + Now.time = Now.resource / Now.klings; + break; + + case E_SNAP: /* take a snapshot of the galaxy */ + xresched(e, E_SNAP, 1); + i = (int) Etc.snapshot; + i = bmove(Quad, i, sizeof (Quad)); + i = bmove(Event, i, sizeof (Event)); + i = bmove(&Now, i, sizeof (Now)); + Game.snap = 1; + break; + + case E_ATTACK: /* Klingons attack during rest period */ + if (!Move.resting) + { + unschedule(e); + break; + } + attack(1); + reschedule(e, 0.5); + break; + + case E_FIXDV: + i = e->systemname; + unschedule(e); + + /* de-damage the device */ + printf("%s reports repair work on the %s finished.\n", + Device[i].person, Device[i].name); + + /* handle special processing upon fix */ + switch (i) + { + + case LIFESUP: + Ship.reserves = Param.reserves; + break; + + case SINS: + if (Ship.cond == DOCKED) + break; + printf("Spock has tried to recalibrate your Space Internal Navigation System,\n"); + printf(" but he has no standard base to calibrate to. Suggest you get\n"); + printf(" to a starbase immediately so that you can properly recalibrate.\n"); + Ship.sinsbad = 1; + break; + + case SSRADIO: + restcancel = dumpssradio(); + break; + } + break; + + default: + break; + } + + if (restcancel && Move.resting && getynpar("Spock: Shall we cancel our rest period")) + Move.time = xdate - idate; + + } + + /* unschedule an attack during a rest period */ + if (e = Now.eventptr[E_ATTACK]) + unschedule(e); + + if (!warp) + { + /* eat up energy if cloaked */ + if (Ship.cloaked) + Ship.energy -= Param.cloakenergy * Move.time; + + /* regenerate resources */ + rtime = 1.0 - exp(-Param.regenfac * Move.time); + Ship.shield += (Param.shield - Ship.shield) * rtime; + Ship.energy += (Param.energy - Ship.energy) * rtime; + + /* decrement life support reserves */ + if (damaged(LIFESUP) && Ship.cond != DOCKED) + Ship.reserves -= Move.time; + } + return (0); +} -- cgit v1.2.3-56-ge451