(linenum→info "unix/slp.c:2238")

bsd-games/2.17/trek/events.c

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