home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume15 / robot_hunt / part02 / driver.c next >
C/C++ Source or Header  |  1993-01-27  |  15KB  |  682 lines

  1. /*
  2.  * Copyright (c) 1985 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. char copyright[] =
  20. "@(#) Copyright (c) 1985 Regents of the University of California.\n\
  21.  All rights reserved.\n";
  22. #endif /* not lint */
  23.  
  24. #ifndef lint
  25. static char sccsid[] = "@(#)driver.c    5.3 (Berkeley) 6/27/88";
  26. #endif /* not lint */
  27.  
  28. /*
  29.  *  Hunt
  30.  *  Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
  31.  *  San Francisco, California
  32.  */
  33.  
  34. # include    "hunt.h"
  35. # include    <signal.h>
  36. # include    <errno.h>
  37. # include    <sys/ioctl.h>
  38. # include    <sys/time.h>
  39. extern int Seed;
  40.  
  41. # ifdef CONSTANT_MOVE
  42. static struct itimerval    Timing;
  43. # endif CONSTANT_MOVE
  44.  
  45. SOCKET    Daemon;
  46. # ifdef    INTERNET
  47. int    Test_socket;        /* test socket to answer datagrams */
  48. # define    DAEMON_SIZE    (sizeof Daemon)
  49. # else INTERNET
  50. # define    DAEMON_SIZE    (sizeof Daemon - 1)
  51. # endif    INTERNET
  52.  
  53. /*
  54.  * main:
  55.  *    The main program.
  56.  */
  57. main()
  58. {
  59.     register PLAYER    *pp;
  60.     register int    had_char;
  61. # ifdef INTERNET
  62.     register long    test_mask;
  63.     int        msg;
  64.     int        namelen;
  65.     SOCKET        test;
  66. # endif INTERNET
  67. # ifdef CONSTANT_MOVE
  68.     register int    enable_alarm, disable_alarm;
  69. # endif CONSTANT_MOVE
  70.     static long    read_fds;
  71.  
  72.     init();
  73.     Sock_mask = (1 << Socket);
  74. # ifdef INTERNET
  75.     test_mask = (1 << Test_socket);
  76. # endif INTERNET
  77.  
  78. # ifdef CONSTANT_MOVE
  79.     enable_alarm = sigblock(0);
  80.     disable_alarm = enable_alarm | (1 << (SIGALRM - 1));
  81.     (void) sigsetmask(disable_alarm);
  82.     (void) signal(SIGALRM, moveshots);
  83. # endif CONSTANT_MOVE
  84.  
  85.     while (Nplayer > 0) {
  86. # ifdef CONSTANT_MOVE
  87.         (void) sigsetmask(enable_alarm);
  88. # endif CONSTANT_MOVE
  89.         read_fds = Fds_mask;
  90.         errno = 0;
  91. # ifndef OLDIPC
  92.         while (select(Num_fds, &read_fds, (int *) NULL,
  93.             (int *) NULL, (struct timeval *) NULL) < 0)
  94. # else OLDIPC
  95.         while (select(20, &read_fds, NULL, 32767) < 0)
  96. # endif OLDIPC
  97.         {
  98.             if (errno != EINTR)
  99.                 perror("select");
  100.             if (Nplayer == 0)
  101.                 goto out;
  102.             errno = 0;
  103.         }
  104.         Have_inp = read_fds;
  105. # ifdef CONSTANT_MOVE
  106.         (void) sigsetmask(disable_alarm);
  107. # endif CONSTANT_MOVE
  108. # ifdef INTERNET
  109.         if (read_fds & test_mask) {
  110.             namelen = DAEMON_SIZE;
  111. # ifndef OLDIPC
  112.             (void) recvfrom(Test_socket, (char *) &msg, sizeof msg,
  113.                 0, (struct sockaddr *) &test, &namelen);
  114.             (void) sendto(Test_socket, (char *) &msg, sizeof msg,
  115.                 0, (struct sockaddr *) &test, DAEMON_SIZE);
  116. # else OLDIPC
  117.             (void) receive(Test_socket, (struct sockaddr *) &test,
  118.                 (char *) &msg, sizeof msg);
  119.             (void) send(Test_socket, (struct sockaddr *) &test,
  120.                 (char *) &msg, sizeof msg);
  121. # endif OLDIPC
  122.         }
  123. # endif INTERNET
  124.         for (;;) {
  125.             had_char = FALSE;
  126.             for (pp = Player; pp < End_player; pp++)
  127.                 if (havechar(pp)) {
  128.                     execute(pp);
  129.                     pp->p_nexec++;
  130.                     had_char++;
  131.                 }
  132. # ifdef MONITOR
  133.             for (pp = Monitor; pp < End_monitor; pp++)
  134.                 if (havechar(pp)) {
  135.                     mon_execute(pp);
  136.                     pp->p_nexec++;
  137.                     had_char++;
  138.                 }
  139. # endif MONITOR
  140.             if (!had_char)
  141.                 break;
  142. # ifdef CONSTANT_MOVE
  143.             for (pp = Player; pp < End_player; pp++) {
  144.                 look(pp);
  145.                 sendcom(pp, REFRESH);
  146.             }
  147. # ifdef MONITOR
  148.             for (pp = Monitor; pp < End_monitor; pp++)
  149.                 sendcom(pp, REFRESH);
  150. # endif MONITOR
  151. # else CONSTANT_MOVE
  152.             moveshots();
  153. # endif CONSTANT_MOVE
  154.             for (pp = Player; pp < End_player; )
  155.                 if (pp->p_death[0] != '\0')
  156.                     zap(pp, TRUE);
  157.                 else
  158.                     pp++;
  159. # ifdef MONITOR
  160.             for (pp = Monitor; pp < End_monitor; )
  161.                 if (pp->p_death[0] != '\0')
  162.                     zap(pp, FALSE);
  163.                 else
  164.                     pp++;
  165. # endif MONITOR
  166.         }
  167.         if (read_fds & Sock_mask)
  168.             answer();
  169.         for (pp = Player; pp < End_player; pp++) {
  170.             if (read_fds & pp->p_mask)
  171.                 sendcom(pp, READY, pp->p_nexec);
  172.             pp->p_nexec = 0;
  173.             (void) fflush(pp->p_output);
  174.         }
  175. # ifdef MONITOR
  176.         for (pp = Monitor; pp < End_monitor; pp++) {
  177.             if (read_fds & pp->p_mask)
  178.                 sendcom(pp, READY, pp->p_nexec);
  179.             pp->p_nexec = 0;
  180.             (void) fflush(pp->p_output);
  181.         }
  182. # endif MONITOR
  183.     }
  184. out:
  185. # ifdef    CONSTANT_MOVE
  186.     bul_alarm(0);
  187. # endif    CONSTANT_MOVE
  188.  
  189. # ifdef MONITOR
  190.     for (pp = Monitor; pp < End_monitor; )
  191.         zap(pp, FALSE);
  192. # endif MONITOR
  193.     cleanup(0);
  194. }
  195.  
  196. /*
  197.  * init:
  198.  *    Initialize the global parameters.
  199.  */
  200. init()
  201. {
  202.     register int    i;
  203. # ifdef    INTERNET
  204.     SOCKET        test_port;
  205.     auto int    msg;
  206. # endif    INTERNET
  207.     int        cleanup();
  208.  
  209. # ifndef DEBUG
  210.     (void) ioctl(fileno(stdout), TIOCNOTTY, NULL);
  211.     (void) setpgrp(getpid(), getpid());
  212.     (void) signal(SIGHUP, SIG_IGN);
  213.     (void) signal(SIGINT, SIG_IGN);
  214.     (void) signal(SIGQUIT, SIG_IGN);
  215.     (void) signal(SIGTERM, cleanup);
  216. # endif DEBUG
  217.  
  218. # ifndef pdp11
  219.     /* Seed the random number generator. */
  220.     srandom (getpid());
  221. # endif pdp11
  222.  
  223.     (void) chdir("/usr/tmp");    /* just in case it core dumps */
  224.     (void) signal(SIGPIPE, SIG_IGN);
  225.  
  226. # ifdef    INTERNET
  227.     Daemon.sin_family = SOCK_FAMILY;
  228. # ifdef OLD
  229.     if (gethostname(local_name, sizeof local_name) < 0) {
  230.         perror("gethostname");
  231.         exit(1);
  232.     }
  233.     if ((hp = gethostbyname(local_name)) == NULL) {
  234.         fprintf(stderr, "Unknown host %s\n", local_name);
  235.         exit(1);
  236.     }
  237.     bcopy(hp->h_addr, &(Daemon.sin_addr.s_addr), hp->h_length);
  238. # else
  239.     Daemon.sin_addr.s_addr = INADDR_ANY;
  240. # endif OLD
  241.     Daemon.sin_port = htons(Sock_port);
  242. # else INTERNET
  243.     Daemon.sun_family = SOCK_FAMILY;
  244.     (void) strcpy(Daemon.sun_path, Sock_name);
  245. # endif INTERNET
  246.  
  247. # ifndef OLDIPC
  248.     Socket = socket(SOCK_FAMILY, SOCK_STREAM, 0);
  249. # else OLDIPC
  250.     Socket = socket(SOCK_STREAM, 0, (struct sockaddr *) &Daemon,
  251.         SO_ACCEPTCONN);
  252. # endif OLDIPC
  253. # if defined(INTERNET) && !defined(OLDIPC)
  254.     msg = 1;
  255.     if (setsockopt(Socket, SOL_SOCKET, SO_REUSEADDR, &msg, sizeof msg)<0)
  256.         perror("setsockopt loopback");
  257. # endif INTERNET
  258. # ifndef OLDIPC
  259.     if (bind(Socket, (struct sockaddr *) &Daemon, DAEMON_SIZE) < 0) {
  260.         if (errno == EADDRINUSE)
  261.             exit(0);
  262.         else {
  263.             perror("bind");
  264.             cleanup(1);
  265.         }
  266.     }
  267.     (void) listen(Socket, 5);
  268. # endif OLDIPC
  269.     Fds_mask = (1 << Socket);
  270.     Num_fds = Socket + 1;
  271.  
  272. # ifdef INTERNET
  273.     test_port = Daemon;
  274.     test_port.sin_port = htons(Test_port);
  275.  
  276. # ifndef OLDIPC
  277.     Test_socket = socket(SOCK_FAMILY, SOCK_DGRAM, 0);
  278.     if (bind(Test_socket, (struct sockaddr *) &test_port,
  279.         DAEMON_SIZE) < 0) {
  280.         perror("bind");
  281.         exit(1);
  282.     }
  283.     (void) listen(Test_socket, 5);
  284. # else OLDIPC
  285.     Test_socket = socket(SOCK_DGRAM, 0, (struct sockaddr *) &test_port, 0);
  286. # endif OLDIPC
  287.     Fds_mask |= (1 << Test_socket);
  288.     if (Test_socket > Socket)
  289.         Num_fds = Test_socket + 1;
  290. # endif    INTERNET
  291.  
  292.     Seed = getpid() + time((time_t *) NULL);
  293.     makemaze();
  294.  
  295.     for (i = 0; i < NASCII; i++)
  296.         See_over[i] = TRUE;
  297.     See_over[DOOR] = FALSE;
  298.     See_over[WALL1] = FALSE;
  299.     See_over[WALL2] = FALSE;
  300.     See_over[WALL3] = FALSE;
  301. # ifdef REFLECT
  302.     See_over[WALL4] = FALSE;
  303.     See_over[WALL5] = FALSE;
  304. # endif REFLECT
  305.  
  306. # ifdef CONSTANT_MOVE
  307.     getitimer(ITIMER_REAL, &Timing);
  308.     Timing.it_interval.tv_sec = 0;
  309.     Timing.it_interval.tv_usec = 500;
  310.     Timing.it_value.tv_sec = 0;
  311.     Timing.it_value.tv_usec = 0;
  312.     setitimer(ITIMER_REAL, &Timing, NULL);
  313. # endif CONSTANT_MOVE
  314.  
  315.     answer();
  316. }
  317.  
  318. # ifdef CONSTANT_MOVE
  319. /*
  320.  * bul_alarm:
  321.  *    Set up the alarm for the bullets
  322.  */
  323. bul_alarm(val)
  324. int    val;
  325. {
  326.     Timing.it_value.tv_usec = val * Timing.it_interval.tv_usec;
  327.     setitimer(ITIMER_REAL, &Timing, NULL);
  328. }
  329. # endif CONSTANT_MOVE
  330.  
  331. /*
  332.  * checkdam:
  333.  *    Check the damage to the given player, and see if s/he is killed
  334.  */
  335. checkdam(ouch, gotcha, credit, amt, shot_type)
  336. register PLAYER    *ouch, *gotcha;
  337. register IDENT    *credit;
  338. int        amt;
  339. char        shot_type;
  340. {
  341.     register char    *cp;
  342.  
  343.     if (ouch->p_death[0] != '\0')
  344.         return;
  345.     if (rand_num(100) < 5) {
  346.         message(ouch, "Missed you by a hair");
  347.         if (gotcha != NULL)
  348.             message(gotcha, "Missed him");
  349.         return;
  350.     }
  351.     ouch->p_damage += amt;
  352.     if (ouch->p_damage <= ouch->p_damcap) {
  353.         (void) sprintf(Buf, "%2d", ouch->p_damage);
  354.         cgoto(ouch, STAT_DAM_ROW, STAT_VALUE_COL);
  355.         outstr(ouch, Buf, 2);
  356.         return;
  357.     }
  358.  
  359.     /* Someone DIED */
  360.     switch (shot_type) {
  361.       default:
  362.         cp = "Killed";
  363.         break;
  364. # ifdef FLY
  365.       case FALL:
  366.         cp = "Killed on impact";
  367.         break;
  368. # endif FLY
  369.       case KNIFE:
  370.         cp = "Stabbed to death";
  371.         break;
  372.       case SHOT:
  373.         cp = "Shot to death";
  374.         break;
  375.       case GRENADE:
  376.       case SATCHEL:
  377.       case BOMB:
  378.         cp = "Bombed";
  379.         break;
  380.       case MINE:
  381.       case GMINE:
  382.         cp = "Blown apart";
  383.         break;
  384. # ifdef    OOZE
  385.       case SLIME:
  386.         cp = "Slimed";
  387.         break;
  388. # endif OOZE
  389. # ifdef    VOLCANO
  390.       case LAVA:
  391.         cp = "Baked";
  392.         break;
  393. # endif VOLCANO
  394.     }
  395.     if (credit == NULL) {
  396.         (void) sprintf(ouch->p_death, "| %s by %s |", cp,
  397.             (shot_type == MINE || shot_type == GMINE) ?
  398.             "a mine" : "act of God");
  399.         return;
  400.     }
  401.  
  402.     (void) sprintf(ouch->p_death, "| %s by %s |", cp, credit->i_name);
  403.  
  404.     credit->i_kills++;
  405.     credit->i_score = credit->i_kills / (double) credit->i_entries;
  406.     if (gotcha == NULL)
  407.         return;
  408.     gotcha->p_damcap += STABDAM;
  409.     gotcha->p_damage -= STABDAM;
  410.     if (gotcha->p_damage < 0)
  411.         gotcha->p_damage = 0;
  412.     (void) sprintf(Buf, "%2d/%2d", gotcha->p_damage, gotcha->p_damcap);
  413.     cgoto(gotcha, STAT_DAM_ROW, STAT_VALUE_COL);
  414.     outstr(gotcha, Buf, 5);
  415.     (void) sprintf(Buf, "%3d", (gotcha->p_damcap - MAXDAM) / 2);
  416.     cgoto(gotcha, STAT_KILL_ROW, STAT_VALUE_COL);
  417.     outstr(gotcha, Buf, 3);
  418.     (void) sprintf(Buf, "%5.2f", gotcha->p_ident->i_score);
  419.     for (ouch = Player; ouch < End_player; ouch++) {
  420.         cgoto(ouch, STAT_PLAY_ROW + 1 + (gotcha - Player),
  421.             STAT_NAME_COL);
  422.         outstr(ouch, Buf, 5);
  423.     }
  424. }
  425.  
  426. /*
  427.  * zap:
  428.  *    Kill off a player and take him out of the game.
  429.  */
  430. zap(pp, was_player)
  431. register PLAYER    *pp;
  432. FLAG        was_player;
  433. {
  434.     register int    i, len;
  435.     register BULLET    *bp;
  436.     register PLAYER    *np;
  437.     register int    x, y;
  438.     int        savefd, savemask;
  439.  
  440.     if (was_player) {
  441.         drawplayer(pp, FALSE);
  442.         Nplayer--;
  443.     }
  444.  
  445.     len = strlen(pp->p_death);    /* Display the cause of death */
  446.     x = (WIDTH - len) / 2;
  447.     cgoto(pp, HEIGHT / 2, x);
  448.     outstr(pp, pp->p_death, len);
  449.     for (i = 1; i < len; i++)
  450.         pp->p_death[i] = '-';
  451.     pp->p_death[0] = '+';
  452.     pp->p_death[len - 1] = '+';
  453.     cgoto(pp, HEIGHT / 2 - 1, x);
  454.     outstr(pp, pp->p_death, len);
  455.     cgoto(pp, HEIGHT / 2 + 1, x);
  456.     outstr(pp, pp->p_death, len);
  457.     cgoto(pp, HEIGHT, 0);
  458.  
  459.     if (Nplayer == 0) {
  460. # ifdef CONSTANT_MOVE
  461.         bul_alarm(0);
  462. # endif CONSTANT_MOVE
  463.         cleanup(0);
  464.         /* NOTREACHED */
  465.     }
  466.  
  467.     savefd = pp->p_fd;
  468.     savemask = pp->p_mask;
  469.  
  470. # ifdef MONITOR
  471.     if (was_player) {
  472. # endif MONITOR
  473.         for (bp = Bullets; bp != NULL; bp = bp->b_next) {
  474.             if (bp->b_owner == pp)
  475.                 bp->b_owner = NULL;
  476.             if (bp->b_x == pp->p_x && bp->b_y == pp->p_y)
  477.                 bp->b_over = SPACE;
  478.         }
  479.  
  480.         i = rand_num(pp->p_ammo);
  481.         if (i == pp->p_ammo - 1) {
  482.             x = pp->p_ammo;
  483.             len = SLIME;
  484.         }
  485.         else if (i >= BOMBREQ) {
  486.             x = BOMBREQ;
  487.             len = BOMB;
  488.         }
  489.         else if (i >= SSLIMEREQ) {
  490.             x = SSLIMEREQ;
  491.             len = SLIME;
  492.         }
  493.         else if (i >= SATREQ) {
  494.             x = SATREQ;
  495.             len = SATCHEL;
  496.         }
  497.         else if (i >= SLIMEREQ) {
  498.             x = SLIMEREQ;
  499.             len = SLIME;
  500.         }
  501.         else if (i >= GRENREQ) {
  502.             x = GRENREQ;
  503.             len = GRENADE;
  504.         }
  505.         else
  506.             x = 0;
  507.         if (x > 0) {
  508.             add_shot(len, pp->p_y, pp->p_x, pp->p_face, x,
  509.                 (PLAYER *) NULL, TRUE, SPACE);
  510.             (void) sprintf(Buf, "%s detonated.",
  511.                 pp->p_ident->i_name);
  512.             for (np = Player; np < End_player; np++)
  513.                 message(np, Buf);
  514. # ifdef MONITOR
  515.             for (np = Monitor; np < End_monitor; np++)
  516.                 message(np, Buf);
  517. # endif MONITOR
  518.         }
  519.  
  520. # ifdef VOLCANO
  521.         volcano += pp->p_ammo - x;
  522.         if (rand_num(100) < volcano / 50) {
  523.             do {
  524.                 x = rand_num(WIDTH / 2) + WIDTH / 4;
  525.                 y = rand_num(HEIGHT / 2) + HEIGHT / 4;
  526.             } while (Maze[y][x] != SPACE);
  527.             add_shot(LAVA, y, x, LEFTS, volcano,
  528.                 (PLAYER *) NULL, TRUE, SPACE);
  529.             for (np = Player; np < End_player; np++)
  530.                 message(np, "Volcano eruption.");
  531.             volcano = 0;
  532.         }
  533. # endif VOLCANO
  534.  
  535.         sendcom(pp, ENDWIN);
  536.         (void) fclose(pp->p_output);
  537.  
  538.         End_player--;
  539.         if (pp != End_player) {
  540.             bcopy((char *) End_player, (char *) pp,
  541.                 sizeof (PLAYER));
  542.             (void) sprintf(Buf, "%5.2f%c%-10.10s",
  543.                 pp->p_ident->i_score, stat_char(pp),
  544.                 pp->p_ident->i_name);
  545.             i = STAT_PLAY_ROW + 1 + (pp - Player);
  546.             for (np = Player; np < End_player; np++) {
  547.                 cgoto(np, i, STAT_NAME_COL);
  548.                 outstr(np, Buf, STAT_NAME_LEN);
  549.             }
  550. # ifdef MONITOR
  551.             for (np = Monitor; np < End_monitor; np++) {
  552.                 cgoto(np, i, STAT_NAME_COL);
  553.                 outstr(np, Buf, STAT_NAME_LEN);
  554.             }
  555. # endif MONITOR
  556.         }
  557.  
  558.         /* Erase the last player */
  559.         i = STAT_PLAY_ROW + 1 + Nplayer;
  560.         for (np = Player; np < End_player; np++) {
  561.             cgoto(np, i, STAT_NAME_COL);
  562.             ce(np);
  563.         }
  564. # ifdef MONITOR
  565.         for (np = Monitor; np < End_monitor; np++) {
  566.             cgoto(np, i, STAT_NAME_COL);
  567.             ce(np);
  568.         }
  569.     }
  570.     else {
  571.         sendcom(pp, ENDWIN);
  572.         (void) putc(LAST_PLAYER, pp->p_output);
  573.         (void) fclose(pp->p_output);
  574.  
  575.         End_monitor--;
  576.         if (pp != End_monitor) {
  577.             bcopy((char *) End_monitor, (char *) pp,
  578.                 sizeof (PLAYER));
  579.             (void) sprintf(Buf, "%5.5s %-10.10s", " ",
  580.                 pp->p_ident->i_name);
  581.             i = STAT_MON_ROW + 1 + (pp - Player);
  582.             for (np = Player; np < End_player; np++) {
  583.                 cgoto(np, i, STAT_NAME_COL);
  584.                 outstr(np, Buf, STAT_NAME_LEN);
  585.             }
  586.             for (np = Monitor; np < End_monitor; np++) {
  587.                 cgoto(np, i, STAT_NAME_COL);
  588.                 outstr(np, Buf, STAT_NAME_LEN);
  589.             }
  590.         }
  591.  
  592.         /* Erase the last monitor */
  593.         i = STAT_MON_ROW + 1 + (End_monitor - Monitor);
  594.         for (np = Player; np < End_player; np++) {
  595.             cgoto(np, i, STAT_NAME_COL);
  596.             ce(np);
  597.         }
  598.         for (np = Monitor; np < End_monitor; np++) {
  599.             cgoto(np, i, STAT_NAME_COL);
  600.             ce(np);
  601.         }
  602.  
  603.     }
  604. # endif MONITOR
  605.  
  606.     Fds_mask &= ~savemask;
  607.     if (Num_fds == savefd + 1) {
  608.         Num_fds = Socket;
  609. # ifdef INTERNET
  610.         if (Test_socket > Socket)
  611.             Num_fds = Test_socket;
  612. # endif INTERNET
  613.         for (np = Player; np < End_player; np++)
  614.             if (np->p_fd > Num_fds)
  615.                 Num_fds = np->p_fd;
  616. # ifdef MONITOR
  617.         for (np = Monitor; np < End_monitor; np++)
  618.             if (np->p_fd > Num_fds)
  619.                 Num_fds = np->p_fd;
  620. # endif MONITOR
  621.         Num_fds++;
  622.     }
  623. }
  624.  
  625. /*
  626.  * havechar:
  627.  *    Check to see if we have any characters in the input queue; if
  628.  *    we do, read them, stash them away, and return TRUE; else return
  629.  *    FALSE.
  630.  */
  631. havechar(pp)
  632. register PLAYER    *pp;
  633. {
  634.     extern int    errno;
  635.  
  636.     if (pp->p_ncount < pp->p_nchar)
  637.         return TRUE;
  638.     if (!(Have_inp & pp->p_mask))
  639.         return FALSE;
  640.     Have_inp &= ~pp->p_mask;
  641. check_again:
  642.     errno = 0;
  643.     if ((pp->p_nchar = read(pp->p_fd, pp->p_cbuf, sizeof pp->p_cbuf)) <= 0)
  644.     {
  645.         if (errno == EINTR)
  646.             goto check_again;
  647.         pp->p_cbuf[0] = 'q';
  648.     }
  649.     pp->p_ncount = 0;
  650.     return TRUE;
  651. }
  652.  
  653. /*
  654.  * cleanup:
  655.  *    Exit with the given value, cleaning up any droppings lying around
  656.  */
  657. cleanup(eval)
  658. int    eval;
  659. {
  660.     register PLAYER    *pp;
  661.  
  662.     for (pp = Player; pp < End_player; pp++) {
  663.         cgoto(pp, HEIGHT, 0);
  664.         sendcom(pp, ENDWIN);
  665.         (void) putc(LAST_PLAYER, pp->p_output);
  666.         (void) fclose(pp->p_output);
  667.     }
  668. # ifdef MONITOR
  669.     for (pp = Monitor; pp < End_monitor; pp++) {
  670.         cgoto(pp, HEIGHT, 0);
  671.         sendcom(pp, ENDWIN);
  672.         (void) putc(LAST_PLAYER, pp->p_output);
  673.         (void) fclose(pp->p_output);
  674.     }
  675. # endif MONITOR
  676.     (void) close(Socket);
  677. # ifdef AF_UNIX_HACK
  678.     (void) unlink(Sock_name);
  679. # endif AF_UNIX_HACK
  680.     exit(eval);
  681. }
  682.