home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / games / xtrek.zip / XTREK1.6 < prev    next >
Text File  |  1987-07-05  |  60KB  |  2,244 lines

  1. Article 47 of comp.sources.games:
  2. Path: ncrcce!rd1632!ncrlnk!ncrcae!ece-csc!mcnc!seismo!rochester!cornell!uw-beaver!tektronix!tekgen!tekred!games-request
  3. From: games-request@tekred.TEK.COM
  4. Newsgroups: comp.sources.games
  5. Subject: v01i073:  xtrek - multiplayer space war game for X-windows, Part01/06
  6. Message-ID: <1366@tekred.TEK.COM>
  7. Date: 2 Jul 87 19:09:41 GMT
  8. Sender: billr@tekred.TEK.COM
  9. Lines: 2230
  10. Approved: billr@tekred.TEK.COM
  11.  
  12. Submitted by: Chris Guthrie <chris%ic.Berkeley.EDU@ucbvax.berkeley.edu>
  13. Comp.sources.games: Volume 1, Issue 73
  14. Archive-name: xtrek/Part01
  15.  
  16.     [The following note is from the author.  (I sure wish I had
  17.      a system with X-windows to play all these neat games!)  -br]
  18.  
  19.     [[xtrek is a game based on the x windowing system.  Typically,
  20.      I've been distributing it through ftp, but I'm getting too
  21.      many requests from people out in uucp land, so I figure that
  22.      sources.games would be appropriate.  People will need to have
  23.      X and sysV shared memory to run the game.  We have it running
  24.      on Ultrix, Sun 3.2, and HP-UX 5.2 machines.]]
  25.  
  26. #! /bin/sh
  27. # This is a shell archive.  Remove anything before this line, then unpack
  28. # it by saving it into a file and typing "sh file".  To overwrite existing
  29. # files, type "sh file -c".  You can also feed this as standard input via
  30. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  31. # will see the following message at the end:
  32. #        "End of archive 1 (of 6)."
  33. # Contents:  README MANIFEST daemon.c rmove.c xtrek.6
  34. # Wrapped by billr@tekred on Thu Jul  2 10:26:27 1987
  35. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  36. if test -f README -a "${1}" != "-c" ; then 
  37.   echo shar: Will not over-write existing file \"README\"
  38. else
  39. echo shar: Extracting \"README\" \(5259 characters\)
  40. sed "s/^X//" >README <<'END_OF_README'
  41. XThis explains quickly how to run xtrek on a ultrix,
  42. XSun 3.20, or HP-UX 5.2 system.  Note that other
  43. Xoperating systems will probably require fiddling.
  44. XThere are notes for various operating systems below.
  45. XThere is also a list of recent changes.
  46. X
  47. XIt is important that the system V shared memory
  48. Xsegments are actually compiled into your kernel on
  49. Xthe server machine.  The clients just need X.
  50. X
  51. XCreate an appropriate directory for it.  The defs.h
  52. Xfile contains the paths to this directory.  If you
  53. Xdon't want it in /usr/games/lib/xtrek, change this
  54. Xfile.
  55. X
  56. XA "make install" will perform the following steps for you.
  57. XIf you don't want xtrek and daemon to be suid to root
  58. Xor you don't like the choice of directories, either
  59. Xchange DESTDIR, XTREKDIR and XTREKOWNER in the Makefile
  60. Xor perform these steps by hand:
  61. X
  62. X    Run make.  Install xtrek in /usr/games.  Robot and
  63. X    daemon must be in /usr/games/lib/xtrek. Create the
  64. X    files .motd, .scores, and .planets in
  65. X    /usr/games/lib/xtrek.
  66. X
  67. X    Xtrek and the daemon must all be setuid
  68. X    to someone who has write permission on these files.
  69. X    Root is fine.  There are no real security holes in
  70. X    the game.  If you want to avoid this, take out the
  71. X    shared memory chmoding and make the dot files writable.
  72. X
  73. XIf you want to change constants in the game, it is
  74. Xpretty well set up to allow tweaking.  Most of the
  75. Xconstants are in defs.h.  Player constants were defined
  76. Xin getship.c in plans for a future custom designed ship
  77. Xoption.
  78. X
  79. Xnroff -me the document and put it somewhere useful.
  80. X
  81. XHP-UX notes:
  82. X
  83. XAlthought I have compiled and run this version of xtrek on
  84. Xan HP-UX 5.2 system, there are some things to be aware of.
  85. XFirst, my system was a 320.  If you have access to a 840 it
  86. Xwould clearly be a better choice as a server.  It would also
  87. Xprovide the wait3 function needed in some of the code.  I don't
  88. Xknow how the wait's I've put into the code will work out.
  89. X
  90. XA 320 system, while being sufficient as a display for the game,
  91. Xwould probably not work well as a server.
  92. X
  93. XSun notes:
  94. X
  95. XSome code was added to prevent people from holding down the
  96. X't' key and generating fields of torps with the auto-repeat
  97. Xmode.  This uses the timer for the xevents and it's not clear
  98. Xthat the timer works everywhere.
  99. X
  100. XThere is one clear bug in the sun Xlib server that can make
  101. Xtorpedoes occasionnally fail to fire.  If you want to fix this
  102. Xbug, replace the line of code in libsun/events.c:
  103. X
  104. X   xe->vse_time = (se->ie_time.tv_usec/10000 + se->ie_time.tv_sec);
  105. X
  106. Xwith
  107. X
  108. X   xe->vse_time = (se->ie_time.tv_usec/10000 + se->ie_time.tv_sec*100);
  109. X
  110. XIt appears twice so get 'em both.  Note that this stuff is in the source
  111. Xto libX.a for the suns.
  112. X
  113. XApollo Notes:
  114. X
  115. XWe don't have an apollo to test the code out, but the following lines
  116. Xin the xlib code scare me:
  117. X
  118. X    /* this needs to be replaced with a "real" timestamp */
  119. X    xe->vse_time += 1;
  120. X
  121. XI suspect that on an apollo, only one torp in ten will actually be fired.
  122. XSee the Sun notes above for more information.
  123. X
  124. XUltrix notes:
  125. X
  126. XBefore running make, look for random.o.  I found
  127. Xthat the ultrix library version wasn't very random,
  128. Xso I substituted the 4.3 one which worked better.
  129. XLicensing agreements being what they are, the
  130. Xversion in this directory just links against
  131. Xwhatever random.o is in libc.a. 
  132. X
  133. XIf you have the 4.3 random.o (or .c), just restore
  134. Xthe commented-out reference to random.o in the Makefile
  135. Xand it will link against your copy. If we ever find a
  136. Xgood public domain rand() function, this problem will
  137. Xgo away.
  138. X
  139. X
  140. XChanges from version 3.0 to version 4.0:
  141. X
  142. XPlayers cannot jump teams once in.  They must quit and rejoin
  143. Xto change teams.
  144. X
  145. XWhen a team loses its last planet, they cannot hold a coup for 30
  146. Xminutes to an hour of play time.
  147. X
  148. XThere is an independent team that controls all planets with zero
  149. Xarmies.
  150. X
  151. XFuel cannot go negative now.
  152. X
  153. XCertain deaths will force you to exit the game completely.
  154. X
  155. XSome colors have been changed.
  156. X
  157. XPlayers may not bomb their own planets.  (Their crews have wives and
  158. Xchildren down there....)
  159. X
  160. XSince sys V compatibility seems to show up in most 4.3 based include
  161. Xfiles, I've gone over to the sys V names of some things like
  162. XSIGCHLD -> SIGCLD.
  163. X
  164. XFixed a bug with showstats that crashed in watch mode.
  165. X
  166. XThere have been a number of changes to 'improve' play.  Not
  167. Xeveryone agrees that they are for the better.  Ships now
  168. Xturn one warp faster.  Fuel is used by the engines -- you
  169. Xdon't gain fuel at warp 5 anymore.
  170. X
  171. XEvents now go through info windows properly.
  172. X
  173. XThe special font effects occur in the info windows.
  174. X
  175. XThe space key will now also close all special windows.
  176. X
  177. XYou cannot repair and use transporters at the same time.
  178. X
  179. XThere are a number of optimizations.  Hardcoding the lengths
  180. Xof planetnames reduced the number of calls to strlen.  The
  181. Xstatus line is now drawn by hand to save calls to doprnt().
  182. XAlso, the characters up on the map window for each ship are
  183. Xstored in the ship's data structure to avoid more calls to
  184. Xdoprnt().
  185. X
  186. XRobots are a little smarter and slightly more aggressive.  This
  187. Xwas meant to stop people from darting in and out while taking
  188. Xperiphery planets.
  189. X
  190. XOverheated weapons can't be wrapped around.
  191. X
  192. XPeople who hold down the 't' key to get a burst of torps are
  193. Xin for a surprise.  Torps cannot be fired faster than one every
  194. Xtenth of a second.
  195. X
  196. END_OF_README
  197. if test 5259 -ne `wc -c <README`; then
  198.     echo shar: \"README\" unpacked with wrong size!
  199. fi
  200. # end of overwriting check
  201. fi
  202. if test -f MANIFEST -a "${1}" != "-c" ; then 
  203.   echo shar: Will not over-write existing file \"MANIFEST\"
  204. else
  205. echo shar: Extracting \"MANIFEST\" \(1374 characters\)
  206. sed "s/^X//" >MANIFEST <<'END_OF_MANIFEST'
  207. X   File Name        Archive #    Description
  208. X-----------------------------------------------------------
  209. X MANIFEST                  1    This shipping list
  210. X Makefile                  4    
  211. X README                    1    
  212. X bitmaps.h                 2    
  213. X clock.bitmap              5    
  214. X colors.c                  5    
  215. X coup.c                    5    
  216. X daemon.c                  1    
  217. X data.c                    5    
  218. X data.h                    5    
  219. X death.c                   5    
  220. X defs.h                    5    
  221. X detonate.c                3    
  222. X dmessage.c                5    
  223. X doc                       2    
  224. X enter.c                   5    
  225. X getship.c                 6    
  226. X inform.c                  4    
  227. X input.c                   3    
  228. X interface.c               5    
  229. X main.c                    4    
  230. X newwin.c                  3    
  231. X orbit.c                   5    
  232. X phaser.c                  5    
  233. X planetlist.c              5    
  234. X planets.h                 5    
  235. X playerlist.c              2    
  236. X pstats.c                  4    
  237. X redraw.c                  3    
  238. X rmove.c                   1    
  239. X robot.c                   5    
  240. X scores.c                  5    
  241. X sintab.c                  4    
  242. X smessage.c                4    
  243. X startdaemon.c             5    
  244. X stats.c                   4    
  245. X struct.h                  4    
  246. X torp.c                    5    
  247. X util.c                    5    
  248. X war.c                     4    
  249. X warning.c                 6    
  250. X xtrek.6                   1    
  251. END_OF_MANIFEST
  252. if test 1374 -ne `wc -c <MANIFEST`; then
  253.     echo shar: \"MANIFEST\" unpacked with wrong size!
  254. fi
  255. # end of overwriting check
  256. fi
  257. if test -f daemon.c -a "${1}" != "-c" ; then 
  258.   echo shar: Will not over-write existing file \"daemon.c\"
  259. else
  260. echo shar: Extracting \"daemon.c\" \(29846 characters\)
  261. sed "s/^X//" >daemon.c <<'END_OF_daemon.c'
  262. X
  263. X/*
  264. X
  265. X    Copyright (c) 1986     Chris Guthrie
  266. X
  267. XPermission to use, copy, modify, and distribute this
  268. Xsoftware and its documentation for any purpose and without
  269. Xfee is hereby granted, provided that the above copyright
  270. Xnotice appear in all copies and that both that copyright
  271. Xnotice and this permission notice appear in supporting
  272. Xdocumentation.  No representations are made about the
  273. Xsuitability of this software for any purpose.  It is
  274. Xprovided "as is" without express or implied warranty.
  275. X
  276. X*/
  277. X
  278. X#include <X/Xlib.h>
  279. X#include <stdio.h>
  280. X#include <sys/types.h>
  281. X#include <sys/ipc.h>
  282. X#include <sys/shm.h>
  283. X#ifdef hpux
  284. X#include <time.h>
  285. X#else hpux
  286. X#include <sys/time.h>
  287. X#endif hpux
  288. X#include <sys/file.h>
  289. X#ifndef hpux
  290. X#include <sys/wait.h>
  291. X#endif hpux
  292. X#include <sys/ioctl.h>
  293. X#include <signal.h>
  294. X#include <setjmp.h>
  295. X#include <math.h>
  296. X#include "defs.h"
  297. X#include "struct.h"
  298. X#include "data.h"
  299. X#include "planets.h"
  300. X
  301. X#ifdef hpux
  302. X#define bcopy(from, to, length)        memcpy((to), (from), (length))
  303. X#endif hpux
  304. X
  305. X#define fuse(X) ((ticks % (X)) == 0)
  306. X/* Run the game */
  307. X
  308. Xlong random();
  309. Xlong lseek();
  310. Xstatic struct itimerval udt;
  311. Xstatic int shmid;
  312. X
  313. Xstatic int debug = 0;
  314. Xstatic int ticks = 0;
  315. Xstatic int plfd;
  316. X
  317. Xjmp_buf env;
  318. X
  319. Xstatic int tcount[MAXTEAM + 1];
  320. X
  321. Xmain(argc, argv)
  322. Xint argc;
  323. Xchar **argv;
  324. X{
  325. X    register int i;
  326. X    int    shmemKey = PKEY;
  327. X    struct memory    *sharedMemory;
  328. X    struct shmid_ds smbuf;
  329. X    int x = 0;
  330. X    int move();
  331. X    int reaper();
  332. X    int freemem();
  333. X
  334. X    if (argc > 1)
  335. X    debug = 1;
  336. X
  337. X    srandom(getpid());
  338. X    if (!debug) {
  339. X    for (i = 0; i < NSIG; i++) {
  340. X        (void) signal(i, freemem);
  341. X    }
  342. X    detach();
  343. X    }
  344. X
  345. X    /* Kill any existing segments */
  346. X
  347. X    if ((shmid = shmget(shmemKey, 0, 0)) >= 0) {
  348. X    fprintf(stderr, "Killing existing segment\n");
  349. X    shmctl(shmid, IPC_RMID, (struct shmid_ds *) 0);
  350. X    }
  351. X
  352. X    shmid = shmget(shmemKey, sizeof(struct memory), IPC_CREAT | 0777);
  353. X    if (shmid < 0) {
  354. X    perror("can't open shared memory");
  355. X    exit (1);
  356. X    }
  357. X    /* Hose Ed's robots */
  358. X    shmctl(shmid, IPC_STAT, &smbuf);
  359. X    smbuf.shm_perm.uid = geteuid();
  360. X    smbuf.shm_perm.mode = 0700;
  361. X    shmctl(shmid, IPC_SET, &smbuf);
  362. X
  363. X    sharedMemory = (struct memory *) shmat(shmid, 0, 0);
  364. X    if (sharedMemory == (struct memory *) -1) {
  365. X    perror("shm attach");
  366. X    exit (1);
  367. X    }
  368. X    players = sharedMemory->players;
  369. X    torps = sharedMemory->torps;
  370. X    status = sharedMemory->status;
  371. X    planets = sharedMemory->planets;
  372. X    phasers = sharedMemory->phasers;
  373. X    mctl = sharedMemory->mctl;
  374. X    messages = sharedMemory->messages;
  375. X
  376. X    for (i = 0; i < MAXPLAYER; i++)
  377. X    players[i].p_status = PFREE;
  378. X
  379. X    plfd = open(PLFILE, O_RDWR, 0777);
  380. X    if (plfd < 0) {
  381. X    fprintf(stderr, "No planet file.  Restarting galaxy\n");
  382. X    bcopy(pdata, planets, sizeof(pdata));
  383. X    for (i = 0; i < 40; i++) {
  384. X        if (planets[i].pl_flags & PLHOME)
  385. X        planets[i].pl_flags |= (PLREPAIR|PLFUEL);
  386. X        if (random() % 4 == 0)
  387. X        planets[i].pl_flags |= PLREPAIR;
  388. X        if (random() % 2 == 0)
  389. X        planets[i].pl_flags |= PLFUEL;
  390. X    }
  391. X    }
  392. X    else {
  393. X    if (read(plfd, (char *) planets, sizeof(pdata)) != sizeof(pdata)) {
  394. X        fprintf(stderr, "Planet file wrong size.  Restarting galaxy\n");
  395. X        bcopy(pdata, planets, sizeof(pdata));
  396. X        for (i = 0; i < 40; i++) {
  397. X        if (planets[i].pl_flags & PLHOME)
  398. X            planets[i].pl_flags |= (PLREPAIR|PLFUEL);
  399. X        if (random() % 4 == 0)
  400. X            planets[i].pl_flags |= PLREPAIR;
  401. X        if (random() % 2 == 0)
  402. X            planets[i].pl_flags |= PLFUEL;
  403. X        }
  404. X    }
  405. X    }
  406. X
  407. X    status->active = 0;
  408. X
  409. X    (void) signal(SIGCLD, reaper);
  410. X
  411. X    (void) signal(SIGALRM, move);
  412. X    udt.it_interval.tv_sec = 0;
  413. X    udt.it_interval.tv_usec = UPDATE;
  414. X    udt.it_value.tv_sec = 0;
  415. X    udt.it_value.tv_usec = UPDATE;
  416. X    (void) setitimer(ITIMER_REAL, &udt, (struct itimerval *) 0);
  417. X
  418. X    (void) setjmp(env);
  419. X
  420. X    while (1) {
  421. X    pause();
  422. X    if (debug) {
  423. X        if (!(++x % 50))
  424. X        printf("Mark %d\n", x);
  425. X    }
  426. X    }
  427. X}
  428. X
  429. Xdetach()
  430. X{
  431. X    int fd;
  432. X
  433. X#ifdef hpux
  434. X    setpgrp();
  435. X#else hpux
  436. X    fd = open("/dev/tty", O_RDWR, 0);
  437. X    if (fd < 0)
  438. X    return;
  439. X    (void) ioctl(fd, TIOCNOTTY, (char *) NULL);
  440. X    (void) close(fd);
  441. X#endif hpux
  442. X}
  443. X
  444. X/* These specify how often special actions will take place in
  445. X   UPDATE units (0.10 seconds, currently.)
  446. X*/
  447. X
  448. X#define PLAYERFUSE    1
  449. X#define TORPFUSE    1
  450. X#define PHASERFUSE    1
  451. X#define TEAMFUSE    5
  452. X#define PLFIGHTFUSE    5
  453. X#define BEAMFUSE    10
  454. X#define SYNCFUSE    3000
  455. X#define PLANETFUSE    600
  456. X
  457. X#define GHOSTTIME    (10 * 1000000 / UPDATE)    /* 10 secs */
  458. X#define OUTFITTIME    (2 * AUTOQUIT * 1000000 / UPDATE) /* 2 * AQ secs */
  459. X
  460. Xnplayers = 0;
  461. Xdietime = -1;
  462. X
  463. Xmove()
  464. X{
  465. X    if (++ticks == dietime)    /* no player for 1 minute. kill self */
  466. X    freemem();
  467. X    if (fuse(PLAYERFUSE)) {
  468. X    udplayers();
  469. X    }
  470. X    if (fuse(TORPFUSE)) {
  471. X    udtorps();
  472. X    }
  473. X    if (fuse(PHASERFUSE)) {
  474. X    udphaser();
  475. X    }
  476. X    if (fuse(TEAMFUSE)) {
  477. X    teamtimers();
  478. X    }
  479. X    if (fuse(PLFIGHTFUSE)) {
  480. X    plfight();
  481. X    }
  482. X    if (fuse(BEAMFUSE)) {
  483. X    beam();
  484. X    }
  485. X    if (fuse(SYNCFUSE)) {
  486. X    save_planets();
  487. X    }
  488. X    if (fuse(PLANETFUSE)) {
  489. X    udplanets();
  490. X    }
  491. X}
  492. X
  493. Xudplayers()
  494. X{
  495. X    register int i, k;
  496. X    register struct player *j;
  497. X    int maxspeed;
  498. X
  499. X    nplayers = 0;
  500. X    tcount[FED] = tcount[ROM] = tcount[KLI] = tcount[ORI] = 0;
  501. X    for (i = status->active = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
  502. X    switch (j->p_status) {
  503. X        case POUTFIT:
  504. X        if (++(j->p_ghostbuster) > OUTFITTIME)
  505. X            j->p_status = PFREE;
  506. X        continue;
  507. X        case PFREE:
  508. X        nplayers++;
  509. X        j->p_ghostbuster = 0;    /* stop from hosing new players */
  510. X        continue;
  511. X        case PDEAD:
  512. X        if (--j->p_explode <= 0) {     /* Ghost Buster */
  513. X            j->p_status = PFREE;
  514. X        }
  515. X        continue;
  516. X        case PEXPLODE:
  517. X        j->p_updates++;
  518. X        j->p_flags &= ~PFCLOAK;
  519. X        if (j->p_explode == (10/PLAYERFUSE))
  520. X            blowup(j);        /* damage everyone else around */
  521. X        if (--j->p_explode <= 0) {
  522. X            j->p_status = PDEAD;
  523. X            j->p_explode = 600/PLAYERFUSE; /* set ghost buster */
  524. X        }
  525. X        break;
  526. X        case PALIVE:
  527. X        if (++(j->p_ghostbuster) > GHOSTTIME) {
  528. X            j->p_status = PEXPLODE;
  529. X            j->p_explode = 10/PLAYERFUSE;
  530. X            ghostmess(j);
  531. X            /* j->p_stats.st_losses++; */
  532. X            j->p_whydead = KGHOST;
  533. X            j->p_whodead = i;
  534. X        }
  535. X            
  536. X        status->active += (1<<i);
  537. X        tcount[j->p_team]++;
  538. X        j->p_updates++;
  539. X
  540. X        /* cool weapons */
  541. X        j->p_wtemp -= 2;
  542. X        if (j->p_wtemp < 0)
  543. X            j->p_wtemp = 0;
  544. X        if (j->p_flags & PFWEP) {
  545. X            if (--j->p_wtime <= 0)
  546. X            j->p_flags &= ~PFWEP;
  547. X        }
  548. X        else if (j->p_wtemp > 1000) {
  549. X            if (!(random() % 40)) {
  550. X            j->p_flags |= PFWEP;
  551. X            j->p_wtime = ((random() % 150) + 100) / PLAYERFUSE;
  552. X            }
  553. X        }
  554. X        /* cool engine */
  555. X        j->p_etemp -= 5;
  556. X        if (j->p_etemp < 0)
  557. X            j->p_etemp = 0;
  558. X        if (j->p_flags & PFENG) {
  559. X            if (--j->p_etime <= 0)
  560. X            j->p_flags &= ~PFENG;
  561. X        }
  562. X        else if (j->p_etemp > 1000) {
  563. X            if (!(random() % 40)) {
  564. X            j->p_flags |= PFENG;
  565. X            j->p_etime = ((random() % 150) + 100) / PLAYERFUSE;
  566. X            j->p_desspeed = 0;
  567. X            }
  568. X        }
  569. X
  570. X        /* Add fuel */
  571. X        if ((j->p_flags & PFORBIT) &&
  572. X            (planets[j->p_planet].pl_flags & PLFUEL) &&
  573. X            (!(planets[j->p_planet].pl_owner 
  574. X            & (j->p_swar | j->p_hostile)))) {
  575. X                j->p_fuel += 8 * j->p_ship.s_recharge;
  576. X        }
  577. X        else
  578. X            j->p_fuel += 2 * j->p_ship.s_recharge;
  579. X
  580. X        if (j->p_fuel > j->p_ship.s_maxfuel)
  581. X            j->p_fuel = j->p_ship.s_maxfuel;
  582. X        if (j->p_fuel < 0) {
  583. X            j->p_desspeed = 0;
  584. X            j->p_flags &= ~PFCLOAK;
  585. X        }
  586. X
  587. X        /* repair shields */
  588. X        if (j->p_shield < 100) {
  589. X            if ((j->p_flags & PFREPAIR) && (j->p_speed == 0)) {
  590. X            j->p_subshield += j->p_ship.s_repair * 4;
  591. X            if ((j->p_flags & PFORBIT) &&
  592. X                (planets[j->p_planet].pl_flags & PLREPAIR) &&
  593. X                (!(planets[j->p_planet].pl_owner 
  594. X                & (j->p_swar | j->p_hostile)))) {
  595. X                    j->p_subshield += j->p_ship.s_repair * 4;
  596. X            }
  597. X            }
  598. X            else
  599. X            j->p_subshield += j->p_ship.s_repair * 2;
  600. X            if (j->p_subshield / 1000) {
  601. X            j->p_shield += j->p_subshield / 1000;
  602. X            j->p_subshield %= 1000;
  603. X            }
  604. X            if (j->p_shield > 100) {
  605. X            j->p_shield = 100;
  606. X            j->p_subshield = 0;
  607. X            }
  608. X        }
  609. X
  610. X        /* repair damage */
  611. X        if (j->p_damage && !(j->p_flags & PFSHIELD)) {
  612. X            if ((j->p_flags & PFREPAIR) && (j->p_speed == 0)) {
  613. X            j->p_subdamage += j->p_ship.s_repair * 2;
  614. X            if ((j->p_flags & PFORBIT) &&
  615. X                (planets[j->p_planet].pl_flags & PLREPAIR) &&
  616. X                (!(planets[j->p_planet].pl_owner 
  617. X                & (j->p_swar | j->p_hostile)))) {
  618. X                    j->p_subdamage += j->p_ship.s_repair * 2;
  619. X            }
  620. X            }
  621. X            else
  622. X            j->p_subdamage += j->p_ship.s_repair;
  623. X            if (j->p_subdamage / 1000) {
  624. X            j->p_damage -= j->p_subdamage / 1000;
  625. X            j->p_subdamage %= 1000;
  626. X            }
  627. X            if (j->p_damage < 0) {
  628. X            j->p_damage = 0;
  629. X            j->p_subdamage = 0;
  630. X            }
  631. X        }
  632. X
  633. X        /* Charge for cloaking */
  634. X        if (j->p_flags & PFCLOAK) {
  635. X            if (j->p_fuel < j->p_ship.s_cloakcost) {
  636. X            j->p_flags &= ~PFCLOAK;
  637. X            }
  638. X            else {
  639. X            j->p_fuel -= j->p_ship.s_cloakcost;
  640. X            }
  641. X        }
  642. X
  643. X        /* Move Player in orbit */
  644. X        if (j->p_flags & PFORBIT) {
  645. X            j->p_dir += 2;
  646. X            j->p_desdir = j->p_dir;
  647. X            j->p_x = planets[j->p_planet].pl_x + ORBDIST
  648. X            * Cos[(unsigned char) (j->p_dir - (unsigned char) 64)];
  649. X            j->p_y = planets[j->p_planet].pl_y + ORBDIST
  650. X            * Sin[(unsigned char) (j->p_dir - (unsigned char) 64)];
  651. X        }
  652. X
  653. X        /* Move player through space */
  654. X        else {
  655. X
  656. X            if (j->p_dir != j->p_desdir)
  657. X            changedir(j);
  658. X
  659. X            /* Alter speed */
  660. X            maxspeed = 10 - j->p_damage/10;
  661. X            if (j->p_desspeed > maxspeed)
  662. X            j->p_desspeed = maxspeed;
  663. X            if (j->p_flags & PFENG)
  664. X            j->p_desspeed = 0;
  665. X
  666. X            if (j->p_desspeed > j->p_speed) {
  667. X            j->p_subspeed += j->p_ship.s_accint;
  668. X            }
  669. X            if (j->p_desspeed < j->p_speed) {
  670. X            j->p_subspeed -= j->p_ship.s_decint;
  671. X            }
  672. X            if (j->p_subspeed / 1000) {
  673. X            j->p_speed += j->p_subspeed / 1000;
  674. X            j->p_subspeed /= 1000;
  675. X            if (j->p_speed < 0)
  676. X                j->p_speed = 0;
  677. X            if (j->p_speed > j->p_ship.s_maxspeed)
  678. X                j->p_speed = j->p_ship.s_maxspeed;
  679. X            }
  680. X            /* Charge for speed */
  681. X
  682. X            if (j->p_fuel < (j->p_ship.s_warpcost * j->p_speed)) {
  683. X            j->p_desspeed = 0;
  684. X            }
  685. X            else {
  686. X            j->p_fuel -= j->p_ship.s_warpcost * j->p_speed;
  687. X            j->p_etemp += j->p_speed;
  688. X            }
  689. X
  690. X            j->p_x += (double) j->p_speed * Cos[j->p_dir] * WARP1;
  691. X            j->p_y += (double) j->p_speed * Sin[j->p_dir] * WARP1;
  692. X
  693. X            /* Bounce off the side of the galaxy */
  694. X            if (j->p_x < 0) {
  695. X            j->p_x = -j->p_x;
  696. X            if (j->p_dir == 192) 
  697. X                j->p_dir = j->p_desdir = 64;
  698. X            else 
  699. X                j->p_dir = j->p_desdir = 64 - (j->p_dir - 192);
  700. X            }
  701. X            else if (j->p_x > GWIDTH) {
  702. X            j->p_x = GWIDTH - (j->p_x - GWIDTH);
  703. X            if (j->p_dir == 64) 
  704. X                j->p_dir = j->p_desdir = 192;
  705. X            else 
  706. X                j->p_dir = j->p_desdir = 192 - (j->p_dir - 64);
  707. X            }
  708. X            if (j->p_y < 0) {
  709. X            j->p_y = -j->p_y;
  710. X            if (j->p_dir == 0) 
  711. X                j->p_dir = j->p_desdir = 128;
  712. X            else 
  713. X                j->p_dir = j->p_desdir = 128 - j->p_dir;
  714. X            }
  715. X            else if (j->p_y > GWIDTH) {
  716. X            j->p_y = GWIDTH - (j->p_y - GWIDTH);
  717. X            if (j->p_dir == 128) 
  718. X                j->p_dir = j->p_desdir = 0;
  719. X            else 
  720. X                j->p_dir = j->p_desdir = 0 - (j->p_dir - 128);
  721. X            }
  722. X        }
  723. X
  724. X        /* Set player's alert status */
  725. X#define YRANGE ((GWIDTH)/5)
  726. X#define RRANGE ((GWIDTH)/10)
  727. X        j->p_flags |= PFGREEN;
  728. X        j->p_flags &= ~(PFRED|PFYELLOW);
  729. X        for (k = 0; k < MAXPLAYER; k++) {
  730. X            int dx, dy, dist;
  731. X            if ((players[k].p_status != PALIVE) ||
  732. X            ((!((j->p_swar | j->p_hostile) & players[k].p_team)) &&
  733. X            (!((players[k].p_swar | players[k].p_hostile) & 
  734. X            j->p_team)))) {
  735. X                continue;
  736. X            }
  737. X            else if (j == &players[k]) {
  738. X            continue;
  739. X            }
  740. X            else {
  741. X            dx = j->p_x - players[k].p_x;
  742. X            dy = j->p_y - players[k].p_y;
  743. X            if (ABS(dx) > YRANGE || ABS(dy) > YRANGE)
  744. X                continue;
  745. X            dist = dx * dx + dy * dy;
  746. X            if (dist <  RRANGE * RRANGE) {
  747. X                j->p_flags |= PFRED;
  748. X                j->p_flags &= ~(PFGREEN|PFYELLOW);
  749. X            }
  750. X            else if ((dist <  YRANGE * YRANGE) &&
  751. X                (!(j->p_flags & PFRED))) {
  752. X                j->p_flags |= PFYELLOW;
  753. X                j->p_flags &= ~(PFGREEN|PFRED);
  754. X            }
  755. X            }
  756. X        }
  757. X        break;
  758. X    } /* end switch */
  759. X    }
  760. X    if (nplayers == MAXPLAYER) {
  761. X    if (dietime == -1)
  762. X        dietime = ticks + 600 / PLAYERFUSE;
  763. X    }
  764. X    else {
  765. X    dietime = -1;
  766. X    }
  767. X}
  768. Xchangedir(sp)
  769. Xstruct player *sp;
  770. X{
  771. X    unsigned int ticks;
  772. X
  773. X    if (sp->p_speed == 0) {
  774. X    sp->p_dir = sp->p_desdir;
  775. X    sp->p_subdir = 0;
  776. X    }
  777. X    else {
  778. X    sp->p_subdir += sp->p_ship.s_turns / (1 << sp->p_speed);
  779. X    ticks = sp->p_subdir / 1000;
  780. X    if (ticks) {
  781. X        if (ticks > ABS(sp->p_dir - sp->p_desdir))
  782. X        sp->p_dir = sp->p_desdir;
  783. X        else if ((unsigned char) (sp->p_dir - sp->p_desdir) > 127)
  784. X        sp->p_dir += ticks;
  785. X        else 
  786. X        sp->p_dir -= ticks;
  787. X        sp->p_subdir %= 1000;
  788. X    }
  789. X    }
  790. X}
  791. X
  792. Xudtorps()
  793. X{
  794. X    register int i;
  795. X    register struct torp *j;
  796. X
  797. X    for (i = 0, j = &torps[i]; i < MAXPLAYER * MAXTORP; i++, j++) {
  798. X    switch (j->t_status) {
  799. X        case TFREE:
  800. X        continue;
  801. X        case TMOVE:
  802. X        case TSTRAIGHT:
  803. X        j->t_x += (double) j->t_speed * Cos[j->t_dir] * WARP1;
  804. X        if (j->t_x < 0) {
  805. X            j->t_x = 0;
  806. X            explode(j);
  807. X            break;
  808. X        }
  809. X        else if (j->t_x > GWIDTH) {
  810. X            j->t_x = GWIDTH;
  811. X            explode(j);
  812. X            break;
  813. X        }
  814. X        j->t_y += (double) j->t_speed * Sin[j->t_dir] * WARP1;
  815. X        if (j->t_y < 0) {
  816. X            j->t_y = 0;
  817. X            explode(j);
  818. X            break;
  819. X        }
  820. X        else if (j->t_y > GWIDTH) {
  821. X            j->t_y = GWIDTH;
  822. X            explode(j);
  823. X            break;
  824. X        }
  825. X
  826. X        /* Make sure that player torps wobble */
  827. X        if (j->t_status == TMOVE)
  828. X            j->t_dir += (random() % 3) - 1;
  829. X
  830. X        if (j->t_fuse-- <= 0) {
  831. X            j->t_status = TFREE;
  832. X            players[j->t_owner].p_ntorp--;
  833. X        }
  834. X        else if (near(j)) {
  835. X            explode(j);
  836. X        }
  837. X        break;
  838. X        case TDET:
  839. X        j->t_x += (double) j->t_speed * Cos[j->t_dir] * WARP1;
  840. X        if (j->t_x < 0)
  841. X            j->t_x += GWIDTH;
  842. X        else if (j->t_x > GWIDTH)
  843. X            j->t_x -= GWIDTH;
  844. X        j->t_y += (double) j->t_speed * Sin[j->t_dir] * WARP1;
  845. X        if (j->t_y < 0)
  846. X            j->t_y += GWIDTH;
  847. X        else if (j->t_y > GWIDTH)
  848. X            j->t_y -= GWIDTH;
  849. X        explode(j);
  850. X        break;
  851. X        case TEXPLODE:
  852. X        if (j->t_fuse-- <= 0) {
  853. X            j->t_status = TFREE;
  854. X            players[j->t_owner].p_ntorp--;
  855. X        }
  856. X        break;
  857. X        case TOFF:
  858. X        j->t_status = TFREE;
  859. X        players[j->t_owner].p_ntorp--;
  860. X        break;
  861. X    }
  862. X    }
  863. X}
  864. X
  865. X/* See if there is someone close enough to explode for */
  866. Xnear(torp)
  867. Xstruct torp *torp;
  868. X{
  869. X    register int i;
  870. X    int dx, dy;
  871. X    register struct player *j;
  872. X
  873. X    for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
  874. X    if (!(j->p_status == PALIVE))
  875. X        continue;
  876. X    if (torp->t_owner == j->p_no)
  877. X        continue;
  878. X    /* This is tricky.  If you aren't at war with the team,
  879. X       and that team is not at war with your team, continue.
  880. X    */
  881. X    if ((!(torp->t_war & j->p_team)) &&
  882. X        (!(torp->t_team & (j->p_swar | j->p_hostile))))
  883. X            continue;
  884. X    dx = torp->t_x - j->p_x;
  885. X    dy = torp->t_y - j->p_y;
  886. X    if (ABS(dx) > EXPDIST || ABS(dy) > EXPDIST)
  887. X        continue;
  888. X    if (dx * dx + dy * dy < EXPDIST * EXPDIST)
  889. X        return 1;
  890. X    }
  891. X    return 0;
  892. X}
  893. X
  894. X    
  895. X
  896. X/* Do damage to all surrounding players */
  897. X
  898. Xexplode(torp)
  899. Xstruct torp *torp;
  900. X{
  901. X    register int i;
  902. X    int dx, dy, dist;
  903. X    int damage;
  904. X    register struct player *j;
  905. X
  906. X    for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
  907. X    if (!(j->p_status == PALIVE))
  908. X        continue;
  909. X    if (torp->t_owner == j->p_no)    /* This isn't realistic */
  910. X        continue;
  911. X    dx = torp->t_x - j->p_x;
  912. X    dy = torp->t_y - j->p_y;
  913. X    if (ABS(dx) > DETDIST || ABS(dy) > DETDIST) /*XXX*/
  914. X        continue;
  915. X    dist = dx * dx + dy * dy;
  916. X    if (dist > DETDIST * DETDIST)
  917. X        continue;
  918. X    if (dist > EXPDIST * EXPDIST) {
  919. X        damage = torp->t_damage * (DETDIST - sqrt((double) dist)) /
  920. X        (DETDIST - EXPDIST);
  921. X    }
  922. X    else {
  923. X        damage = torp->t_damage;
  924. X    }
  925. X    if (damage > 0) {
  926. X        /* First, check to see if torp owner has started a war */
  927. X        if (players[torp->t_owner].p_hostile & j->p_team) {
  928. X        players[torp->t_owner].p_swar |= j->p_team;
  929. X        }
  930. X        /* Note that if a player is at peace with the victim, then
  931. X           the torp has caused damage either accidently, or because
  932. X           the victim was at war with, or hostile to, the player.
  933. X           In either case, we don't consider the damage to be
  934. X           an act of war */
  935. X
  936. X        if (j->p_flags & PFSHIELD) {
  937. X        j->p_shield -= damage;
  938. X        if (j->p_shield < 0) {
  939. X            j->p_damage -= j->p_shield;
  940. X            j->p_shield = 0;
  941. X        }
  942. X        }
  943. X        else {
  944. X        j->p_damage += damage;
  945. X        }
  946. X        if (j->p_damage >= 100) {
  947. X        j->p_status = PEXPLODE;
  948. X        j->p_explode = 10/PLAYERFUSE;
  949. X        if (!(j->p_flags & PFPRACTR)) {
  950. X            players[torp->t_owner].p_kills += 1.0 + 
  951. X            j->p_armies * 0.1 + j->p_kills * 0.1;
  952. X        }
  953. X        killmess(j, &players[torp->t_owner]);
  954. X        j->p_stats.st_losses++;
  955. X        j->p_whydead = KTORP;
  956. X        j->p_whodead = torp->t_owner;
  957. X        }
  958. X    }
  959. X    }
  960. X    torp->t_status = TEXPLODE;
  961. X    torp->t_fuse = 10/TORPFUSE;
  962. X}
  963. X
  964. Xudplanets()
  965. X{
  966. X    register int i;
  967. X    register struct planet *l;
  968. X
  969. X    for (i = 0, l = &planets[i]; i < MAXPLANETS; i++, l++) {
  970. X    if (l->pl_couptime)    /* Decrement coup counter one minute */
  971. X        l->pl_couptime--;
  972. X    if (l->pl_armies == 0)
  973. X        continue;
  974. X    if ((random() % 3000) < l->pl_armies)
  975. X        l->pl_armies -= (random() % l->pl_armies);
  976. X    if ((l->pl_armies < 4) && ((random() % 20) == 0)) {
  977. X        l->pl_armies++;
  978. X        continue;
  979. X    }
  980. X    if ((random() % 10) == 0)
  981. X        l->pl_armies += (random() % 3) + 1;
  982. X        
  983. X    }
  984. X}
  985. X
  986. Xudphaser()
  987. X{
  988. X    register int i;
  989. X    register struct phaser *j;
  990. X    register struct player *victim;
  991. X
  992. X    for (i = 0, j = &phasers[i]; i < MAXPLAYER; i++, j++) {
  993. X    switch (j->ph_status) {
  994. X        case PHFREE:
  995. X        continue;
  996. X        case PHMISS:
  997. X        if (j->ph_fuse-- == 1)
  998. X            j->ph_status = PHFREE;
  999. X        break;
  1000. X        case PHHIT:
  1001. X        if (j->ph_fuse-- == 10) {
  1002. X            victim = &players[j->ph_target];
  1003. X
  1004. X            /* start a war, if necessary */
  1005. X            if (players[i].p_hostile & victim->p_team) {
  1006. X            players[i].p_swar |= victim->p_team;
  1007. X            }
  1008. X
  1009. X            if (victim->p_flags & PFSHIELD) {
  1010. X            victim->p_shield -= j->ph_damage;
  1011. X            if (victim->p_shield < 0) {
  1012. X                victim->p_damage -= victim->p_shield;
  1013. X                victim->p_shield = 0;
  1014. X            }
  1015. X            }
  1016. X            else {
  1017. X            victim->p_damage += j->ph_damage;
  1018. X            }
  1019. X            if (victim->p_damage >= 100) {
  1020. X            victim->p_status = PEXPLODE;
  1021. X            victim->p_explode = 10/PLAYERFUSE;
  1022. X            if (!(victim->p_flags & PFPRACTR)) {
  1023. X                players[i].p_kills += 1.0 + 
  1024. X                victim->p_armies * 0.1 +
  1025. X                victim->p_kills * 0.1;
  1026. X            }
  1027. X            killmess(victim, &players[i]);
  1028. X            victim->p_stats.st_losses++;
  1029. X            victim->p_whydead = KPHASER;
  1030. X            victim->p_whodead = i;
  1031. X            }
  1032. X        }
  1033. X        if (j->ph_fuse == 0)
  1034. X            j->ph_status = PHFREE;
  1035. X        break;
  1036. X    }
  1037. X    }
  1038. X}
  1039. X
  1040. Xint pl_warning[MAXPLANETS];    /* To keep planets shut up for awhile */
  1041. Xint tm_robots[MAXTEAM + 1];        /* To limit the number of robots */
  1042. Xint tm_coup[MAXTEAM + 1];        /* To allow a coup */
  1043. X
  1044. Xteamtimers()
  1045. X{
  1046. X    register int i;
  1047. X    for (i = 0; i <= MAXTEAM; i++) {
  1048. X    if (tm_robots[i] > 0)
  1049. X        tm_robots[i]--;
  1050. X    if (tm_coup[i] > 0)
  1051. X        tm_coup[i]--;
  1052. X    }
  1053. X}
  1054. X
  1055. Xplfight()
  1056. X{
  1057. X    register int h, i;
  1058. X    register struct player *j;
  1059. X    register struct planet *l;
  1060. X    int dx, dy;
  1061. X    int damage;
  1062. X    int dist;
  1063. X    int rnd;
  1064. X    char buf[80];
  1065. X    char buf1[80];
  1066. X
  1067. X    for (h = 0, l = &planets[h]; h < MAXPLANETS; h++, l++) {
  1068. X    if (l->pl_flags & PLCOUP) {
  1069. X        l->pl_flags &= ~PLCOUP;
  1070. X        l->pl_owner = (l->pl_flags & ALLTEAM);
  1071. X        l->pl_armies = 4;
  1072. X    }
  1073. X    l->pl_flags &= ~PLREDRAW;
  1074. X    if (pl_warning[h] > 0)
  1075. X        pl_warning[h]--;
  1076. X    }
  1077. X    for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
  1078. X    if (j->p_status == PALIVE) {
  1079. X
  1080. X        /* Have planets do damage to nearby players.  Note that
  1081. X           this is the most inefficient code in the game.  If
  1082. X           one needs cycles, simply change the code to have
  1083. X           planets only attack ships that are in orbit.   Thus
  1084. X           you get rid of the following for statement 
  1085. X        */
  1086. X        for (h = 0, l = &planets[h]; h < MAXPLANETS; h++, l++) {
  1087. X        dx = ABS(l->pl_x - j->p_x);
  1088. X        dy = ABS(l->pl_y - j->p_y);
  1089. X        if (dx < 3 * PFIREDIST && dy < 3 * PFIREDIST)
  1090. X            l->pl_flags |= PLREDRAW;
  1091. X        if (dx > PFIREDIST || dy > PFIREDIST)    /*XXX*/
  1092. X            continue;
  1093. X        dist = (int) hypot((double) dx, (double) dy);
  1094. X        if (dist > PFIREDIST)
  1095. X            continue;
  1096. X        if ((j->p_swar | j->p_hostile) & l->pl_owner) {
  1097. X            if (l->pl_armies > 0)
  1098. X            damage = l->pl_armies / 10 + 2;
  1099. X            else
  1100. X            damage = 0;
  1101. X            if (damage > 0) {
  1102. X            if (j->p_flags & PFSHIELD) {
  1103. X                j->p_shield -= damage;
  1104. X                if (j->p_shield < 0) {
  1105. X                j->p_damage -= j->p_shield;
  1106. X                j->p_shield = 0;
  1107. X                }
  1108. X            }
  1109. X            else {
  1110. X                j->p_damage += damage;
  1111. X            }
  1112. X            if (j->p_damage >= 100) {
  1113. X            j->p_explode = 10/PLAYERFUSE;
  1114. X            j->p_status = PEXPLODE;
  1115. X            j->p_stats.st_losses++;
  1116. X            (void) sprintf(buf, "%s (%c%x) killed by %s (%c)",
  1117. X                j->p_name,
  1118. X                teamlet[j->p_team],
  1119. X                j->p_no,
  1120. X                l->pl_name,
  1121. X                teamlet[l->pl_owner]);
  1122. X            pmessage(buf, 0, MALL, "GOD->ALL");
  1123. X            j->p_whydead = KPLANET;
  1124. X            j->p_whodead = h;
  1125. X            }
  1126. X            }
  1127. X        }
  1128. X        }    /* End planet damage */
  1129. X
  1130. X        /* do bombing */
  1131. X        if ((!(j->p_flags & PFORBIT)) || (!(j->p_flags & PFBOMB)))
  1132. X        continue;
  1133. X        l = &planets[j->p_planet];
  1134. X        if (j->p_team == l->pl_owner)
  1135. X        continue;
  1136. X        if (!((j->p_swar | j->p_hostile) & l->pl_owner))
  1137. X        continue;
  1138. X        if (l->pl_armies < 5)
  1139. X        continue;
  1140. X
  1141. X        /* Warn owning team */
  1142. X        if (pl_warning[h] <= 0) {
  1143. X        pl_warning[h] = 50/PLFIGHTFUSE; 
  1144. X        (void) sprintf(buf, "We are being attacked by %s %c%x.",
  1145. X            j->p_name,
  1146. X            teamlet[j->p_team],
  1147. X            j->p_no);
  1148. X        (void) sprintf(buf1, "%-3s->%-3s",
  1149. X            l->pl_name, teamshort[l->pl_owner]);
  1150. X        pmessage(buf, l->pl_owner, MTEAM, buf1);
  1151. X        }
  1152. X
  1153. X        /* start the war (if necessary) */
  1154. X        j->p_swar |= l->pl_owner;
  1155. X
  1156. X        rnd = random() % 100;
  1157. X        if (rnd < 50) {
  1158. X        continue;
  1159. X        }
  1160. X        else if (rnd < 80) {
  1161. X        l->pl_armies -= 1;
  1162. X        j->p_kills += 0.02;
  1163. X        j->p_stats.st_armsbomb++;
  1164. X        }
  1165. X        else if (rnd < 90) {
  1166. X        l->pl_armies -= 2;
  1167. X        j->p_kills += 0.04;
  1168. X        j->p_stats.st_armsbomb += 2;
  1169. X        }
  1170. X        else  {
  1171. X        l->pl_armies -= 3;
  1172. X        j->p_kills += 0.06;
  1173. X        j->p_stats.st_armsbomb += 3;
  1174. X        }
  1175. X
  1176. X        /* Send in a robot if there are no other defenders 
  1177. X        and the planet is in the team's home space */
  1178. X
  1179. X        if ((tcount[l->pl_owner] == 0) && 
  1180. X        (l->pl_flags & l->pl_owner) &&
  1181. X            tm_robots[l->pl_owner] == 0) {
  1182. X            rescue(l->pl_owner, j->p_kills);
  1183. X            tm_robots[l->pl_owner] = (1800 + 
  1184. X                (random() % 1800)) /
  1185. X                TEAMFUSE;
  1186. X        }
  1187. X    }
  1188. X    }
  1189. X}
  1190. X
  1191. Xbeam()
  1192. X{
  1193. X    register int i;
  1194. X    register struct player *j;
  1195. X    register struct planet *l;
  1196. X    char buf[80];
  1197. X    char buf1[80];
  1198. X
  1199. X    for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
  1200. X    if ((j->p_status != PALIVE) || (!(j->p_flags & PFORBIT)))
  1201. X        continue;
  1202. X    l = &planets[j->p_planet];
  1203. X    if (j->p_flags & PFBEAMUP) {
  1204. X        if (l->pl_armies < 5)
  1205. X        continue;
  1206. X        if (j->p_armies == j->p_ship.s_maxarmies)
  1207. X        continue;
  1208. X        /* XXX */
  1209. X        if (j->p_armies == floor(j->p_kills * 2.0))
  1210. X        continue;
  1211. X        if (j->p_team != l->pl_owner)
  1212. X        continue;
  1213. X        if ((j->p_swar | j->p_hostile) & l->pl_owner)
  1214. X        continue;
  1215. X        j->p_armies++;
  1216. X        l->pl_armies--;
  1217. X        continue;
  1218. X    }
  1219. X    if (j->p_flags & PFBEAMDOWN) {
  1220. X        if (j->p_armies == 0)
  1221. X        continue;
  1222. X        if ((!((j->p_swar | j->p_hostile) & l->pl_owner))
  1223. X         && (j->p_team != l->pl_owner) && (l->pl_owner != NOBODY))
  1224. X        continue;
  1225. X        if (j->p_team != l->pl_owner) {
  1226. X        j->p_armies--;
  1227. X        if (l->pl_armies) {
  1228. X            int oldowner = l->pl_owner;
  1229. X
  1230. X            /* start the war (if necessary) */
  1231. X            j->p_swar |= l->pl_owner;
  1232. X
  1233. X            l->pl_armies--;
  1234. X            j->p_kills += 0.02;
  1235. X            j->p_stats.st_armsbomb++;
  1236. X            if (l->pl_armies == 0) {
  1237. X            /* Give planet to nobody */
  1238. X            (void) sprintf(buf, "%s destroyed by %s (%c%x)",
  1239. X                l->pl_name,
  1240. X                j->p_name,
  1241. X                teamlet[j->p_team],
  1242. X                j->p_no);
  1243. X            (void) sprintf(buf1, "%-3s->%-3s",
  1244. X                l->pl_name, teamshort[l->pl_owner]);
  1245. X            pmessage(buf, l->pl_owner, MTEAM, buf1);
  1246. X            l->pl_owner = NOBODY;
  1247. X            checkgen(oldowner, j);
  1248. X            }
  1249. X        }
  1250. X        else {     /* planet taken over */
  1251. X            l->pl_armies++;
  1252. X            j->p_stats.st_planets++;
  1253. X            j->p_kills += 0.25;
  1254. X            (void) sprintf(buf, "%s taken over by %s (%c%x)",
  1255. X            l->pl_name,
  1256. X            j->p_name,
  1257. X            teamlet[j->p_team],
  1258. X            j->p_no);
  1259. X            l->pl_owner = j->p_team;
  1260. X            l->pl_info = j->p_team;
  1261. X            checkwin(j);
  1262. X            /* now tell new team */
  1263. X            (void) sprintf(buf1, "%-3s->%-3s",
  1264. X            l->pl_name, teamshort[l->pl_owner]);
  1265. X            pmessage(buf, l->pl_owner, MTEAM, buf1);
  1266. X        }
  1267. X        }
  1268. X        else {
  1269. X        j->p_armies--;
  1270. X        l->pl_armies++;
  1271. X        }
  1272. X    }
  1273. X
  1274. X    }
  1275. X}
  1276. X
  1277. Xblowup(sh)
  1278. Xstruct player *sh;
  1279. X{
  1280. X    register int i;
  1281. X    int dx, dy, dist;
  1282. X    int damage;
  1283. X    register struct player *j;
  1284. X
  1285. X    for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
  1286. X    if (j->p_status != PALIVE)
  1287. X        continue;
  1288. X    if (sh == j)
  1289. X        continue;
  1290. X    /* the following keeps people from blowing up on others */
  1291. X    me = sh;
  1292. X    if ((me->p_whydead == KQUIT) && (friendlyPlayer(j)))
  1293. X        continue;
  1294. X    dx = sh->p_x - j->p_x;
  1295. X    dy = sh->p_y - j->p_y;
  1296. X    if (ABS(dx) > DETDIST || ABS(dy) > DETDIST)
  1297. X        continue;
  1298. X    dist = dx * dx + dy * dy;
  1299. X    if (dist > DETDIST * DETDIST)
  1300. X        continue;
  1301. X    if (dist > EXPDIST * EXPDIST) {
  1302. X        damage = 100 * (DETDIST - sqrt((double) dist)) /
  1303. X        (DETDIST - EXPDIST);
  1304. X    }
  1305. X    else {
  1306. X        damage = 100;
  1307. X    }
  1308. X    if (damage > 0) {
  1309. X        if (j->p_flags & PFSHIELD) {
  1310. X        j->p_shield -= damage;
  1311. X        if (j->p_shield < 0) {
  1312. X            j->p_damage -= j->p_shield;
  1313. X            j->p_shield = 0;
  1314. X        }
  1315. X        }
  1316. X        else {
  1317. X        j->p_damage += damage;
  1318. X        }
  1319. X        if (j->p_damage >= 100) {
  1320. X        j->p_status = PEXPLODE;
  1321. X        j->p_explode = 10;
  1322. X        if (!(j->p_flags & PFPRACTR)) {
  1323. X            sh->p_kills += 1.0 + 
  1324. X            j->p_armies * 0.1 + j->p_kills * 0.1;
  1325. X        }
  1326. X        killmess(j, sh);
  1327. X        j->p_stats.st_losses++;
  1328. X        j->p_whydead = KSHIP;
  1329. X        j->p_whodead = sh->p_no;
  1330. X        }
  1331. X    }
  1332. X    }
  1333. X}
  1334. X
  1335. Xfreemem()
  1336. X{
  1337. X    register int i;
  1338. X    register struct player *j;
  1339. X
  1340. X    /* Blow players out of the game */
  1341. X    for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
  1342. X    j->p_status = PDEAD;
  1343. X    j->p_whydead = KDAEMON;
  1344. X    j->p_ntorp = 0;
  1345. X    }
  1346. X    save_planets();
  1347. X    sleep(2);
  1348. X    shmctl(shmid, IPC_RMID, (struct shmid_ds *) 0);
  1349. X    exit(0);
  1350. X}
  1351. X
  1352. Xsave_planets()
  1353. X{
  1354. X    if (plfd >= 0) {
  1355. X    (void) lseek(plfd, (long) 0, 0);
  1356. X    (void) write(plfd, (char *) planets, sizeof(pdata));
  1357. X    }
  1358. X}
  1359. X/* This function checks to see if a team has been genocided --
  1360. X   their last planet has been beamed down to zero.  It will set
  1361. X   a timer on their home planet that will prevent them from
  1362. X   couping for a random number of minutes.
  1363. X*/
  1364. Xcheckgen(loser, winner)
  1365. Xint loser;
  1366. Xstruct player *winner;
  1367. X{
  1368. X    register int i;
  1369. X    register struct planet *l;
  1370. X    struct planet *homep;
  1371. X
  1372. X    for (i = 0, l = &planets[i]; i < MAXPLANETS; i++, l++) {
  1373. X    if (l->pl_owner == loser)
  1374. X        return;
  1375. X    if (((l->pl_flags & ALLTEAM) == loser) && (l->pl_flags & PLHOME))
  1376. X        homep = l;        /* Keep track of his home planet for marking */
  1377. X    }
  1378. X
  1379. X    /* well, I guess they are losers.  Hose them now */
  1380. X    winner->p_stats.st_genocides++;
  1381. X    homep->pl_couptime = (18000 + (random() % 18000)) / PLANETFUSE;
  1382. X}
  1383. X
  1384. X
  1385. X/* This function is called when a planet has been taken over.
  1386. X   It checks all the planets to see if the victory conditions
  1387. X   are right.  If so, it blows everyone out of the game and
  1388. X   resets the galaxy
  1389. X*/
  1390. Xcheckwin(winner)
  1391. Xstruct player *winner;
  1392. X{
  1393. X    register int i, h;
  1394. X    register struct planet *l;
  1395. X    register struct player *j;
  1396. X    int team[MAXTEAM + 1];
  1397. X
  1398. X    for (i = 0; i < 4; i++)
  1399. X    team[1<<i] = 0;
  1400. X    
  1401. X    for (i = 0, l = &planets[i]; i < MAXPLANETS; i++, l++)
  1402. X    team[l->pl_owner]++;
  1403. X
  1404. X    for (i = 0; i < 4; i++) {
  1405. X    if (team[1<<i] >= VICTORY) {
  1406. X        /* We have a winning team */
  1407. X        for (h = 0, j = &players[0]; h < MAXPLAYER; h++, j++) {
  1408. X        j->p_status = PDEAD;
  1409. X        j->p_whydead = KWINNER;
  1410. X        j->p_whodead = winner->p_no;
  1411. X        j->p_ntorp = 0;
  1412. X        }
  1413. X        winner->p_stats.st_conqs++;
  1414. X        bcopy(pdata, planets, sizeof(pdata));
  1415. X        for (i = 0; i < 40; i++) {
  1416. X        if (random() % 4 == 0)
  1417. X            planets[i].pl_flags |= PLREPAIR;
  1418. X        if (random() % 2 == 0)
  1419. X            planets[i].pl_flags |= PLFUEL;
  1420. X        }
  1421. X        longjmp(env, 0);
  1422. X    }
  1423. X    }
  1424. X}
  1425. X
  1426. Xpmessage(str, recip, group, addr)
  1427. Xchar *str;
  1428. Xint recip;
  1429. Xint group;
  1430. Xchar *addr;
  1431. X{
  1432. X    struct message *cur;
  1433. X
  1434. X    if (++(mctl->mc_current) >= MAXMESSAGE)
  1435. X    mctl->mc_current = 0;
  1436. X    cur = &messages[mctl->mc_current];
  1437. X    cur->m_no = mctl->mc_current;
  1438. X    cur->m_flags = group;
  1439. X    cur->m_time = ticks;
  1440. X    cur->m_recpt = recip;
  1441. X    (void) sprintf(cur->m_data, "%s %s", addr, str);
  1442. X    cur->m_flags |= MVALID;
  1443. X}
  1444. X
  1445. Xghostmess(victim)
  1446. X    struct player    *victim;
  1447. X{
  1448. X    char         buf[80];
  1449. X    static float    ghostkills = 0.0;
  1450. X
  1451. X    ghostkills += 1.0 + victim->p_armies * 0.1 + victim->p_kills * 0.1;
  1452. X    (void) sprintf(buf, "%s (%c%x) was kill %0.2f for the GhostBusters",
  1453. X    victim->p_name, teamlet[victim->p_team], victim->p_no, ghostkills);
  1454. X    pmessage(buf, 0, MALL, "GOD->ALL");
  1455. X}
  1456. X
  1457. Xkillmess(victim, killer)
  1458. Xstruct player *victim, *killer;
  1459. X{
  1460. X    char buf[80];
  1461. X
  1462. X    (void) sprintf(buf, "%s (%c%x) was kill %0.2f for %s (%c%x)",
  1463. X    victim->p_name,
  1464. X    teamlet[victim->p_team],
  1465. X    victim->p_no,
  1466. X    killer->p_kills,
  1467. X    killer->p_name,
  1468. X    teamlet[killer->p_team],
  1469. X    killer->p_no);
  1470. X    pmessage(buf, 0, MALL, "GOD->ALL");
  1471. X}
  1472. X
  1473. X/* Send in a robot to avenge the aggrieved team */
  1474. Xrescue(team, kills)
  1475. Xint team;
  1476. Xfloat kills;
  1477. X{
  1478. X    char *arg1;
  1479. X    char *arg2 = "-lX";
  1480. X
  1481. X    if (fork() == 0) {
  1482. X    (void) close(0);
  1483. X    (void) close(1);
  1484. X    (void) close(2);
  1485. X    (void) signal(SIGALRM, SIG_DFL);
  1486. X    switch (team) {
  1487. X        case FED:
  1488. X        arg1 = "-Tf";
  1489. X        break;
  1490. X        case ROM:
  1491. X        arg1 = "-Tr";
  1492. X        break;
  1493. X        case KLI:
  1494. X        arg1 = "-Tk";
  1495. X        break;
  1496. X        case ORI:
  1497. X        arg1 = "-To";
  1498. X        break;
  1499. X    }
  1500. X    if (kills > 9.0)
  1501. X        kills = 9.0;
  1502. X    (void) sprintf(arg2, "-l%d", (int) kills);
  1503. X    execl(ROBOT, "robot", arg1, arg2, 0);
  1504. X    /* If we get here, we are hosed anyway */
  1505. X    }
  1506. X}
  1507. X
  1508. X#include <sys/resource.h>
  1509. X
  1510. X/* Don't fear the ... */
  1511. X
  1512. Xreaper(sig)
  1513. X{
  1514. X#ifdef hpux
  1515. X    wait((int *) 0);
  1516. X#else hpux
  1517. X    while (wait3((union wait *) 0, WNOHANG, (struct rusage *) 0) > 0)
  1518. X    ;
  1519. X#endif hpux
  1520. X}
  1521. X
  1522. X#ifdef hpux
  1523. X
  1524. Xsrandom(foo)
  1525. Xint foo;
  1526. X{
  1527. X    rand(foo);
  1528. X}
  1529. X
  1530. Xrandom()
  1531. X{
  1532. X    return(rand());
  1533. X}
  1534. X
  1535. Xgetrusage(foo, buf)
  1536. Xint foo;
  1537. Xstruct rusage *buf;
  1538. X{
  1539. X    buf->ru_utime.tv_sec = 0;
  1540. X    buf->ru_stime.tv_sec = 0;
  1541. X}
  1542. X
  1543. X#include <sys/signal.h>
  1544. X
  1545. Xint (*
  1546. Xsignal(sig, funct))()
  1547. Xint sig;
  1548. Xint (*funct)();
  1549. X{
  1550. X    struct sigvec vec, oldvec;
  1551. X
  1552. X    sigvector(sig, 0, &vec);
  1553. X    vec.sv_handler = funct;
  1554. X    sigvector(sig, &vec, (struct sigvec *) 0);
  1555. X}
  1556. X
  1557. X#endif hpux
  1558. END_OF_daemon.c
  1559. if test 29846 -ne `wc -c <daemon.c`; then
  1560.     echo shar: \"daemon.c\" unpacked with wrong size!
  1561. fi
  1562. # end of overwriting check
  1563. fi
  1564. if test -f rmove.c -a "${1}" != "-c" ; then 
  1565.   echo shar: Will not over-write existing file \"rmove.c\"
  1566. else
  1567. echo shar: Extracting \"rmove.c\" \(14954 characters\)
  1568. sed "s/^X//" >rmove.c <<'END_OF_rmove.c'
  1569. X
  1570. X/*
  1571. X
  1572. X    Copyright (c) 1986     Chris Guthrie
  1573. X
  1574. XPermission to use, copy, modify, and distribute this
  1575. Xsoftware and its documentation for any purpose and without
  1576. Xfee is hereby granted, provided that the above copyright
  1577. Xnotice appear in all copies and that both that copyright
  1578. Xnotice and this permission notice appear in supporting
  1579. Xdocumentation.  No representations are made about the
  1580. Xsuitability of this software for any purpose.  It is
  1581. Xprovided "as is" without express or implied warranty.
  1582. X
  1583. X*/
  1584. X
  1585. X#include <X/Xlib.h>
  1586. X#include <stdio.h>
  1587. X#include <signal.h>
  1588. X#include <math.h>
  1589. X#include "defs.h"
  1590. X#include "struct.h"
  1591. X#include "data.h"
  1592. X
  1593. X#define SIZEOF(s)        (sizeof (s) / sizeof (*(s)))
  1594. X#define AVOID_TIME        4
  1595. X#define AVOID_CLICKS        200
  1596. X
  1597. X#define NORMALIZE(d)         ((((d) % 256) + 256) % 256)
  1598. X
  1599. X#define E_INTRUDER    0x01
  1600. X#define E_TSHOT        0x02
  1601. X#define E_PSHOT     0x04
  1602. X
  1603. Xstruct Enemy {
  1604. X    int e_info;
  1605. X    int e_dist;
  1606. X    unsigned char e_course;    /* course to enemy */
  1607. X    unsigned char e_tcourse;    /* torpedo intercept course to enemy */
  1608. X    unsigned int e_flags;
  1609. X};
  1610. X
  1611. Xint timer;
  1612. Xstatic int avoidTime;
  1613. Xstatic unsigned short tok;
  1614. X
  1615. Xextern int debug;
  1616. Xextern int hostile;
  1617. Xextern int sticky;
  1618. Xextern int practice;
  1619. X
  1620. Xunsigned char    getcourse();
  1621. X
  1622. Xrmove()
  1623. X{
  1624. X    register int i;
  1625. X    register int burst;
  1626. X    register int numHits, tDir;
  1627. X    int        avDir;
  1628. X    extern struct Enemy *get_nearest();
  1629. X    struct Enemy *enemy_buf;
  1630. X    struct player *enemy;
  1631. X    static int    clock = 0;
  1632. X    static int    avoid[2] = { -32, 32 };
  1633. X    int no_cloak;
  1634. X
  1635. X    clock++;
  1636. X    /* Check that I'm alive */
  1637. X    if (me->p_status == PEXPLODE) {
  1638. X    signal(SIGALRM, SIG_IGN);
  1639. X    while (me->p_status == PEXPLODE)
  1640. X        ;
  1641. X    while (me->p_ntorp > 0)
  1642. X        ;
  1643. X    me->p_status = PFREE;
  1644. X    exit(0);
  1645. X    }
  1646. X    if (me->p_status == PDEAD) {
  1647. X    signal(SIGALRM, SIG_IGN);
  1648. X    me->p_status = PFREE;
  1649. X    exit(0);
  1650. X    }
  1651. X
  1652. X    /* keep ghostbuster away */
  1653. X    me->p_ghostbuster = 0;
  1654. X
  1655. X    /* Find an enemy */
  1656. X
  1657. X    enemy_buf = get_nearest();
  1658. X
  1659. X    if (enemy_buf > 0) {            /* Someone to kill */
  1660. X    enemy = &players[enemy_buf->e_info];
  1661. X    timer = 0;
  1662. X    if (debug)
  1663. X        fprintf(stderr, "%d) noticed %d\n", me->p_no, enemy->p_no);
  1664. X    }
  1665. X    else if (enemy_buf < 0) { /* no more players. wait 1 minute. */
  1666. X    if (!sticky) {
  1667. X        if (timer == 0)
  1668. X        timer = me->p_updates + 600;
  1669. X        if (me->p_updates >= timer) {
  1670. X        signal(SIGALRM, SIG_IGN);
  1671. X        me->p_status = PFREE;
  1672. X        exit(0);
  1673. X        }
  1674. X    }
  1675. X    if (do_repair()) {
  1676. X        return;
  1677. X    }
  1678. X    go_home(0);
  1679. X    if (debug)
  1680. X        fprintf(stderr, "%d) No players in game.\n", me->p_no);
  1681. X    return;
  1682. X    }
  1683. X    else if (enemy_buf == 0) {     /* no one hostile */
  1684. X    if (debug)
  1685. X        fprintf(stderr, "%d) No hostile players in game.\n", me->p_no);
  1686. X    if (do_repair()) {
  1687. X        return;
  1688. X    }
  1689. X    go_home(0);
  1690. X    timer = 0;
  1691. X    return;
  1692. X    }
  1693. X
  1694. X/* Algorithm:
  1695. X** We have an enemy.
  1696. X** First priority: shoot at target in range.
  1697. X** Second: Dodge torps.
  1698. X** Third: Get away if we are damaged.
  1699. X** Fourth: repair.
  1700. X** Fifth: attack.
  1701. X*/
  1702. X
  1703. X/*
  1704. X** If we are a practice robot, we will do all but the second.  One
  1705. X** will be modified to shoot poorly and not use phasers.
  1706. X**/
  1707. X    /* Fire weapons!!! */
  1708. X    /*
  1709. X    ** get_nearest() has already determined if torpedoes and phasers
  1710. X    ** will hit.  It has also determined the courses which torps and
  1711. X    ** phasers should be fired.  If so we will go ahead and shoot here.
  1712. X    ** We will lose repair and cloaking for the rest of this interrupt.
  1713. X    ** if we fire here.
  1714. X    */
  1715. X
  1716. X    if (practice) {
  1717. X    no_cloak = 1;
  1718. X    if (enemy_buf->e_flags & E_TSHOT) {
  1719. X        if (debug)
  1720. X        fprintf(stderr, "%d) firing torps\n", me->p_no);
  1721. X        for (burst = 0; (burst < 3) && (me->p_ntorp < MAXTORP); burst++) {
  1722. X        tok += 11;
  1723. X        ntorp(enemy_buf->e_tcourse, TMOVE, tok);
  1724. X        }
  1725. X    }
  1726. X    }
  1727. X    else {
  1728. X    no_cloak = 0;
  1729. X    if (enemy_buf->e_flags & E_TSHOT) {
  1730. X        if (debug)
  1731. X        fprintf(stderr, "%d) firing torps\n", me->p_no);
  1732. X        for (burst = 0; (burst < 2) && (me->p_ntorp < MAXTORP); burst++) {
  1733. X        repair_off();
  1734. X        cloak_off();
  1735. X        tok += 11;
  1736. X        ntorp(enemy_buf->e_tcourse, TSTRAIGHT, tok);
  1737. X        no_cloak++;
  1738. X        }
  1739. X    }
  1740. X    if (enemy_buf->e_flags & E_PSHOT) {
  1741. X        if (debug)
  1742. X        fprintf(stderr, "%d) phaser firing\n", me->p_no);
  1743. X        no_cloak++;
  1744. X        repair_off();
  1745. X        cloak_off();
  1746. X        phaser(enemy_buf->e_course);
  1747. X    }
  1748. X    }
  1749. X
  1750. X    /* Avoid torps */
  1751. X    /*
  1752. X    ** This section of code allows robots to avoid torps.
  1753. X    ** Within a specific range they will check to see if
  1754. X    ** any of the 'closest' enemies torps will hit them.
  1755. X    ** If so, they will evade for four updates.
  1756. X    ** Evading is all they will do for this round, other than shooting.
  1757. X    */
  1758. X
  1759. X    if (!practice) {
  1760. X    if (enemy->p_ntorp < 5) {
  1761. X        if ((enemy_buf->e_dist < 15000) || (avoidTime > 0)) {
  1762. X        numHits = projectDamage(enemy->p_no, &avDir);
  1763. X        if (debug) {
  1764. X            fprintf(stderr, "%d hits expected from %d from dir = %d\n",
  1765. X                numHits, enemy->p_no, avDir);
  1766. X        }
  1767. X        if (numHits == 0) {
  1768. X            if (--avoidTime > 0) {    /* we may still be avoiding */
  1769. X            if (angdist(me->p_desdir, me->p_dir) > 64)
  1770. X                me->p_desspeed = 3;
  1771. X            else
  1772. X                me->p_desspeed = 5;
  1773. X            return;
  1774. X            }
  1775. X        } else {
  1776. X            /*
  1777. X             * Actually avoid Torps
  1778. X             */ 
  1779. X            avoidTime = AVOID_TIME;
  1780. X            tDir = avDir - me->p_dir;
  1781. X            /* put into 0->255 range */
  1782. X            tDir = NORMALIZE(tDir);
  1783. X            if (debug)
  1784. X            fprintf(stderr, "mydir = %d avDir = %d tDir = %d q = %d\n",
  1785. X                me->p_dir, avDir, tDir, tDir / 64);
  1786. X            switch (tDir / 64) {
  1787. X            case 0:
  1788. X            case 1:
  1789. X                me->p_desdir = NORMALIZE(avDir + 64);
  1790. X                break;
  1791. X            case 2:
  1792. X            case 3:
  1793. X                me->p_desdir = NORMALIZE(avDir - 64);
  1794. X                break;
  1795. X            }
  1796. X            if (!no_cloak)
  1797. X            cloak_on();
  1798. X
  1799. X            if (angdist(me->p_desdir, me->p_dir) > 64)
  1800. X            me->p_desspeed = 3;
  1801. X            else
  1802. X            me->p_desspeed = 5;
  1803. X            
  1804. X            shield_up();
  1805. X            if (debug)
  1806. X            fprintf(stderr, "evading to dir = %d\n", me->p_desdir);
  1807. X            return;
  1808. X        }
  1809. X        }
  1810. X    }
  1811. X
  1812. X    /*
  1813. X    ** Trying another scheme.
  1814. X    ** Robot will keep track of the number of torps a player has
  1815. X    ** launched.  If they are greater than say four, the robot will
  1816. X    ** veer off immediately.  Seems more humanlike to me.
  1817. X    */
  1818. X
  1819. X    else if (enemy_buf->e_dist < 15000) {
  1820. X        if (--avoidTime > 0) {    /* we may still be avoiding */
  1821. X        if (angdist(me->p_desdir, me->p_dir) > 64)
  1822. X            me->p_desspeed = 3;
  1823. X        else
  1824. X            me->p_desspeed = 5;
  1825. X        return;
  1826. X        }
  1827. X        if (random() % 2) {
  1828. X        me->p_desdir = NORMALIZE(enemy_buf->e_course - 64);
  1829. X        avoidTime = AVOID_TIME;
  1830. X        }
  1831. X        else {
  1832. X        me->p_desdir = NORMALIZE(enemy_buf->e_course + 64);
  1833. X        avoidTime = AVOID_TIME;
  1834. X        }
  1835. X        if (angdist(me->p_desdir, me->p_dir) > 64)
  1836. X        me->p_desspeed = 3;
  1837. X        else
  1838. X        me->p_desspeed = 5;
  1839. X        shield_up();
  1840. X        return;
  1841. X    }
  1842. X    }
  1843. X        
  1844. X    /* Run away */
  1845. X    /*
  1846. X    ** The robot has taken damage.  He will now attempt to run away from
  1847. X    ** the closest player.  This obviously won't do him any good if there
  1848. X    ** is another player in the direction he wants to go.
  1849. X    ** Note that the robot will not run away if he dodged torps, above.
  1850. X    ** The robot will lower his shields in hopes of repairing some damage.
  1851. X    */
  1852. X
  1853. X    if (me->p_damage > 0 && enemy_buf->e_dist < 13000) {
  1854. X    if (me->p_etemp > 900)        /* 90% of 1000 */
  1855. X        me->p_desspeed = 5;
  1856. X    else
  1857. X        me->p_desspeed = 6;
  1858. X    if (!no_cloak)
  1859. X        cloak_on();
  1860. X    repair_off();
  1861. X    shield_down();
  1862. X    me->p_desdir = enemy_buf->e_course - 128;
  1863. X    if (debug)
  1864. X        fprintf(stderr, "%d(%d)(%d/%d) running from %c%d %16s damage (%d/%d) dist %d\n",
  1865. X        me->p_no,
  1866. X        (int) me->p_kills,
  1867. X        me->p_damage,
  1868. X        me->p_shield,
  1869. X        teamlet[enemy->p_team],
  1870. X        enemy->p_no,
  1871. X        enemy->p_login,
  1872. X        enemy->p_damage,
  1873. X        enemy->p_shield,
  1874. X        enemy_buf->e_dist);
  1875. X    return;
  1876. X    }
  1877. X
  1878. X    /* Repair if necessary (we are safe) */
  1879. X    /*
  1880. X    ** The robot is safely away from players.  It can now repair in peace.
  1881. X    ** It will try to do so now.
  1882. X    */
  1883. X
  1884. X    if (do_repair()) {
  1885. X    return;
  1886. X    }
  1887. X
  1888. X    /* Attack. */
  1889. X    /*
  1890. X    ** The robot has nothing to do.  It will check and see if the nearest
  1891. X    ** enemy fits any of its criterion for attack.  If it does, the robot
  1892. X    ** will speed in and deliver a punishing blow.  (Well, maybe)
  1893. X    */
  1894. X
  1895. X    if ((enemy_buf->e_flags & E_INTRUDER) || (enemy_buf->e_dist < 15000)
  1896. X    || (hostile)) {
  1897. X    if ((!no_cloak) && (enemy_buf->e_dist < 10000))
  1898. X        cloak_on();
  1899. X    shield_up();
  1900. X    if (debug)
  1901. X        fprintf(stderr, "%d(%d)(%d/%d) attacking %c%d %16s damage (%d/%d) dist %d\n",
  1902. X        me->p_no,
  1903. X        (int) me->p_kills,
  1904. X        me->p_damage,
  1905. X        me->p_shield,
  1906. X        teamlet[enemy->p_team],
  1907. X        enemy->p_no,
  1908. X        enemy->p_login,
  1909. X        enemy->p_damage,
  1910. X        enemy->p_shield,
  1911. X        enemy_buf->e_dist);
  1912. X
  1913. X    if (enemy_buf->e_dist < 15000) {
  1914. X        me->p_desdir = enemy_buf->e_course + 
  1915. X            avoid[(clock / AVOID_CLICKS) % SIZEOF(avoid)];
  1916. X        if (angdist(me->p_desdir, me->p_dir) > 64)
  1917. X        me->p_desspeed = 3;
  1918. X        else
  1919. X        me->p_desspeed = 4;
  1920. X    }
  1921. X    else {
  1922. X        me->p_desdir = enemy_buf->e_course;
  1923. X        if (angdist(me->p_desdir, me->p_dir) > 64)
  1924. X        me->p_desspeed = 3;
  1925. X        else if (me->p_etemp > 900)        /* 90% of 1000 */
  1926. X        me->p_desspeed = 5;
  1927. X        else
  1928. X        me->p_desspeed = 6;
  1929. X    }
  1930. X    }
  1931. X    else {
  1932. X    go_home(enemy_buf);
  1933. X    }
  1934. X}
  1935. X
  1936. Xunsigned char
  1937. Xgetcourse(x, y)
  1938. Xint x, y;
  1939. X{
  1940. X    return((unsigned char) (atan2((double) (x - me->p_x),
  1941. X        (double) (me->p_y - y)) / 3.14159 * 128.));
  1942. X}
  1943. X
  1944. Xstruct {
  1945. X    int x;
  1946. X    int y;
  1947. X} center[] = { {0, 0},
  1948. X        {GWIDTH / 4, GWIDTH * 3 / 4},        /* Fed */
  1949. X        {GWIDTH / 4, GWIDTH / 4},        /* Rom */
  1950. X        {0, 0},
  1951. X        {GWIDTH * 3 / 4, GWIDTH  / 4},        /* Kli */
  1952. X        {0, 0},
  1953. X        {0, 0},
  1954. X        {0, 0},
  1955. X        {GWIDTH * 3 / 4, GWIDTH * 3 / 4}};    /* Ori */
  1956. X
  1957. X/* This function means that the robot has nothing better to do.
  1958. X   If there are hostile players in the game, it will try to get
  1959. X   as close to them as it can, while staying in it's on space.
  1960. X   Otherwise, it will head to the center of its own space.
  1961. X*/
  1962. Xgo_home(ebuf)
  1963. Xstruct Enemy *ebuf;
  1964. X{
  1965. X    int x, y, speed;
  1966. X    double dx, dy;
  1967. X    int tdist;
  1968. X    struct player *j;
  1969. X
  1970. X    if (ebuf == 0) {  /* No enemies */
  1971. X    if (debug)
  1972. X        fprintf(stderr, "%d) No enemies\n", me->p_no);
  1973. X    x = center[me->p_team].x;
  1974. X    y = center[me->p_team].y;
  1975. X    }
  1976. X    else {    /* Let's get near him */
  1977. X    j = &players[ebuf->e_info];
  1978. X    x = j->p_x;
  1979. X    y = j->p_y;
  1980. X    switch (me->p_team) {
  1981. X        case FED:
  1982. X        if (x > (GWIDTH/2) - 5000)
  1983. X            x = (GWIDTH/2) - 5000;
  1984. X        if (y < (GWIDTH/2) + 5000)
  1985. X            y = (GWIDTH/2) + 5000;
  1986. X        break;
  1987. X        case ROM:
  1988. X        if (x > (GWIDTH/2) - 5000)
  1989. X            x = (GWIDTH/2) - 5000;
  1990. X        if (y > (GWIDTH/2) - 5000)
  1991. X            y = (GWIDTH/2) - 5000;
  1992. X        break;
  1993. X        case KLI:
  1994. X        if (x < (GWIDTH/2) + 5000)
  1995. X            x = (GWIDTH/2) + 5000;
  1996. X        if (y > (GWIDTH/2) - 5000)
  1997. X            y = (GWIDTH/2) - 5000;
  1998. X        break;
  1999. X        case ORI:
  2000. X        if (x < (GWIDTH/2) + 5000)
  2001. X            x = (GWIDTH/2) + 5000;
  2002. X        if (y < (GWIDTH/2) + 5000)
  2003. X            y = (GWIDTH/2) + 5000;
  2004. X        break;
  2005. X    }
  2006. X    }
  2007. X    if (debug)
  2008. X    fprintf(stderr, "%d) moving towards (%d/%d)\n",
  2009. X        me->p_no, x, y);
  2010. X
  2011. X    /* Note that I've decided that robots should never stop moving.
  2012. X    ** It makes them too easy to kill
  2013. X    */
  2014. X
  2015. X    me->p_desdir = getcourse(x, y);
  2016. X    if (angdist(me->p_desdir, me->p_dir) > 64)
  2017. X    me->p_desspeed = 3;
  2018. X    else if (me->p_etemp > 900)        /* 90% of 1000 */
  2019. X    me->p_desspeed = 5;
  2020. X    else {
  2021. X    dx = x - me->p_x;
  2022. X    dy = y - me->p_y;
  2023. X    me->p_desspeed = (hypot(dx, dy) / 5000) + 3;
  2024. X    }
  2025. X    cloak_off();
  2026. X}
  2027. X
  2028. XprojectDamage(eNum, dirP)
  2029. X    int    *dirP;
  2030. X{
  2031. X    register int        i, j, numHits = 0, mx, my, tx, ty, dx, dy;
  2032. X    double            tdx, tdy, mdx, mdy;
  2033. X    register struct torp    *t;
  2034. X
  2035. X    *dirP = 0;
  2036. X    for (i = 0, t = &torps[eNum * MAXTORP]; i < MAXTORP; i++, t++) {
  2037. X        if (t->t_status == TFREE)
  2038. X            continue;
  2039. X        tx = t->t_x; ty = t->t_y;
  2040. X        mx = me->p_x; my = me->p_y;
  2041. X        tdx = (double) t->t_speed * Cos[t->t_dir] * WARP1;
  2042. X        tdy = (double) t->t_speed * Sin[t->t_dir] * WARP1;
  2043. X        mdx = (double) me->p_speed * Cos[me->p_dir] * WARP1;
  2044. X        mdy = (double) me->p_speed * Sin[me->p_dir] * WARP1;
  2045. X        for (j = t->t_fuse; j > 0; j--) {
  2046. X            tx += tdx; ty += tdy;
  2047. X            mx += mdx; my += mdy;
  2048. X            dx = tx - mx; dy = ty - my;
  2049. X            if (ABS(dx) < EXPDIST && ABS(dy) < EXPDIST) {
  2050. X                numHits++;
  2051. X                *dirP += t->t_dir;
  2052. X                break;
  2053. X            }
  2054. X        }
  2055. X    }
  2056. X    if (numHits > 0)
  2057. X        *dirP /= numHits;
  2058. X    return (numHits);
  2059. X}
  2060. X
  2061. Xstruct Enemy ebuf;
  2062. X
  2063. Xstruct Enemy *
  2064. Xget_nearest()
  2065. X{
  2066. X    int pcount = 0;
  2067. X    register int i;
  2068. X    register struct player *j;
  2069. X    int intruder = 0;
  2070. X    int tdist;
  2071. X    double dx, dy;
  2072. X
  2073. X    /* Find an enemy */
  2074. X    ebuf.e_info = me->p_no;
  2075. X    ebuf.e_dist = GWIDTH + 1;
  2076. X
  2077. X    pcount = 0;  /* number of human players in game */
  2078. X
  2079. X    /* avoid dead slots, me, other robots (which aren't hostile) */
  2080. X    for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
  2081. X    if ((j->p_status != PALIVE) || (j == me) ||
  2082. X        ((j->p_flags & PFROBOT) && (!hostile)))
  2083. X        continue;
  2084. X    else
  2085. X        pcount++;    /* Other players in the game */
  2086. X    if (((j->p_swar | j->p_hostile) & me->p_team)
  2087. X        || ((me->p_swar | me->p_hostile) & j->p_team)) {
  2088. X        /* We have an enemy */
  2089. X        /* Get his range */
  2090. X        dx = j->p_x - me->p_x;
  2091. X        dy = j->p_y - me->p_y;
  2092. X        tdist = hypot(dx, dy);
  2093. X
  2094. X        /* Check to see if ship is in our space. */
  2095. X        switch (me->p_team) {
  2096. X        case FED:
  2097. X            intruder = ((j->p_x < GWIDTH/2) && (j->p_y > GWIDTH/2));
  2098. X            break;
  2099. X        case ROM:
  2100. X            intruder = ((j->p_x < GWIDTH/2) && (j->p_y < GWIDTH/2));
  2101. X            break;
  2102. X        case KLI:
  2103. X            intruder = ((j->p_x > GWIDTH/2) && (j->p_y < GWIDTH/2));
  2104. X            break;
  2105. X        case ORI:
  2106. X            intruder = ((j->p_x > GWIDTH/2) && (j->p_y > GWIDTH/2));
  2107. X            break;
  2108. X        }
  2109. X
  2110. X        if (tdist < ebuf.e_dist) {
  2111. X        ebuf.e_info = i;
  2112. X        ebuf.e_dist = tdist;
  2113. X        if (intruder)
  2114. X            ebuf.e_flags |= E_INTRUDER;
  2115. X        else
  2116. X            ebuf.e_flags &= ~(E_INTRUDER);
  2117. X        }
  2118. X    }
  2119. X    }
  2120. X    if (pcount == 0)
  2121. X    return ((struct Enemy *) -1);    /* no players in game */
  2122. X    else if (ebuf.e_info == me->p_no)
  2123. X    return (0);            /* no hostile players in the game */
  2124. X    else {
  2125. X    j = &players[ebuf.e_info];
  2126. X
  2127. X    /* Get torpedo course to nearest enemy */
  2128. X    ebuf.e_flags &= ~(E_TSHOT);
  2129. X    for (i = 0; i < 50; i++) {
  2130. X        double  he_x, he_y, area;
  2131. X
  2132. X        he_x = j->p_x + Cos[j->p_dir] * j->p_speed * i * WARP1;
  2133. X        he_y = j->p_y + Sin[j->p_dir] * j->p_speed * i * WARP1;
  2134. X        area = i * me->p_ship.s_torpspeed * WARP1;
  2135. X        if (hypot(he_x - me->p_x, he_y - me->p_y) < area) {
  2136. X        ebuf.e_flags |= E_TSHOT;
  2137. X        ebuf.e_tcourse = getcourse((int) he_x, (int) he_y);
  2138. X        break;
  2139. X        }
  2140. X    }
  2141. X    /*
  2142. X    if (debug)
  2143. X        fprintf(stderr, "torpedo course to enemy %d is %d (%d) - %s\n", 
  2144. X            j->p_no,
  2145. X            (int) ebuf.e_tcourse,
  2146. X            (int) ebuf.e_tcourse * 360 / 256,
  2147. X            (ebuf.e_flags & E_TSHOT) ? "aiming to hit" :
  2148. X            "no hit possible");
  2149. X    */
  2150. X
  2151. X    /* Get phaser shot status */
  2152. X    if (ebuf.e_dist < 5000)
  2153. X        ebuf.e_flags |= E_PSHOT;
  2154. X    else
  2155. X        ebuf.e_flags &= ~(E_PSHOT);
  2156. X
  2157. X    /* get course info */
  2158. X    ebuf.e_course = getcourse(j->p_x, j->p_y);
  2159. X    /*
  2160. X    if (debug)
  2161. X        fprintf(stderr, "Set course to enemy is %d (%d)\n",
  2162. X            (int)ebuf.e_course, 
  2163. X            (int) ebuf.e_course * 360 / 256);
  2164. X    */
  2165. X
  2166. X    return (&ebuf);
  2167. X    }
  2168. X}
  2169. X
  2170. Xdo_repair()
  2171. X{
  2172. X/* Repair if necessary (we are safe) */
  2173. X
  2174. X    if (me->p_damage > 0) {
  2175. X    me->p_desspeed = 0;
  2176. X    cloak_off();
  2177. X    shield_down();
  2178. X    me->p_desspeed = 0;
  2179. X    if (me->p_speed == 0)
  2180. X        repair();
  2181. X    if (debug)
  2182. X        fprintf(stderr, "%d) repairing damage at %d\n",
  2183. X        me->p_no,
  2184. X        me->p_damage);
  2185. X    return(1);
  2186. X    }
  2187. X    else {
  2188. X    return (0);
  2189. X    }
  2190. X}
  2191. END_OF_rmove.c
  2192. if test 14954 -ne `wc -c <rmove.c`; then
  2193.     echo shar: \"rmove.c\" unpacked with wrong size!
  2194. fi
  2195. # end of overwriting check
  2196. fi
  2197. if test -f xtrek.6 -a "${1}" != "-c" ; then 
  2198.   echo shar: Will not over-write existing file \"xtrek.6\"
  2199. else
  2200. echo shar: Extracting \"xtrek.6\" \(472 characters\)
  2201. sed "s/^X//" >xtrek.6 <<'END_OF_xtrek.6'
  2202. X.TH XTREK 6 "19 Sept 1986"
  2203. X.SH NAME
  2204. Xxtrek \- X based multi-player space shoot 'em up game
  2205. X.SH SYNOPSIS
  2206. X.B xtrek
  2207. X[ monitor:0 ]
  2208. X.SH DESCRIPTION
  2209. X.I Xtrek
  2210. Xis a game based on shared memory and the X window environment.
  2211. XIt is thoroughly described in xtrek.doc which probably lives
  2212. Xin /usr/games/lib/xtrek/xtrek.doc.
  2213. X.SH OPTIONS
  2214. X.I Xtrek
  2215. Xwill get the monitor name from your environment unless
  2216. Xit is specified on the command line.
  2217. X.SH AUTHOR
  2218. XChris Guthrie (chris@ic.berkeley.edu)
  2219. END_OF_xtrek.6
  2220. if test 472 -ne `wc -c <xtrek.6`; then
  2221.     echo shar: \"xtrek.6\" unpacked with wrong size!
  2222. fi
  2223. # end of overwriting check
  2224. fi
  2225. echo shar: End of archive 1 \(of 6\).
  2226. cp /dev/null ark1isdone
  2227. MISSING=""
  2228. for I in 1 2 3 4 5 6 ; do
  2229.     if test ! -f ark${I}isdone ; then
  2230.     MISSING="${MISSING} ${I}"
  2231.     fi
  2232. done
  2233. if test "${MISSING}" = "" ; then
  2234.     echo You have unpacked all 6 archives.
  2235.     rm -f ark[1-9]isdone
  2236. else
  2237.     echo You still need to unpack the following archives:
  2238.     echo "        " ${MISSING}
  2239. fi
  2240. ##  End of shell archive.
  2241. exit 0
  2242.  
  2243.  
  2244.