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

bsd-games/2.17/hunt/huntd/answer.c

    1: /*      $NetBSD: answer.c,v 1.7 2004/11/05 21:30:32 dsl Exp $        */
    2: /*
    3:  * Copyright (c) 1983-2003, Regents of the University of California.
    4:  * All rights reserved.
    5:  * 
    6:  * Redistribution and use in source and binary forms, with or without 
    7:  * modification, are permitted provided that the following conditions are 
    8:  * met:
    9:  * 
   10:  * + Redistributions of source code must retain the above copyright 
   11:  *   notice, this list of conditions and the following disclaimer.
   12:  * + Redistributions in binary form must reproduce the above copyright 
   13:  *   notice, this list of conditions and the following disclaimer in the 
   14:  *   documentation and/or other materials provided with the distribution.
   15:  * + Neither the name of the University of California, San Francisco nor 
   16:  *   the names of its contributors may be used to endorse or promote 
   17:  *   products derived from this software without specific prior written 
   18:  *   permission.
   19:  * 
   20:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
   21:  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
   22:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
   23:  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
   24:  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
   25:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
   26:  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
   27:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
   28:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
   29:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
   30:  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31:  */
   32: 
   33: #include <sys/cdefs.h>
   34: #ifndef lint
   35: __RCSID("$NetBSD: answer.c,v 1.7 2004/11/05 21:30:32 dsl Exp $");
   36: #endif /* not lint */
   37: 
   38: # include       <ctype.h>
   39: # include       <errno.h>
   40: # include       <fcntl.h>
   41: # include       <stdlib.h>
   42: # include       <unistd.h>
   43: # include       <sys/time.h>
   44: # include       "hunt.h"
   45: 
   46: # define        SCOREDECAY     15
   47: 
   48: static char     Ttyname[NAMELEN];
   49: 
   50: int
   51: answer()
   52: {
   53:         PLAYER                 *pp;
   54:         int                    newsock;
   55:         static u_long          mode;
   56:         static char            name[NAMELEN];
   57:         static char            team;
   58:         static int             enter_status;
   59:         static int             socklen;
   60:         static u_long          machine;
   61:         static u_int32_t       uid;
   62:         static SOCKET          sockstruct;
   63:         char                   *cp1, *cp2;
   64:         int                    flags;
   65:         u_int32_t              version;
   66:         int                    i;
   67: 
   68: # ifdef INTERNET
   69:         socklen = sizeof sockstruct;
   70: # else
   71:         socklen = sizeof sockstruct - 1;
   72: # endif
   73:         errno = 0;
   74:         newsock = accept(Socket, (struct sockaddr *) &sockstruct, &socklen);
   75:         if (newsock < 0)
   76:         {
   77:                 if (errno == EINTR)
   78:                         return FALSE;
   79: # ifdef LOG
   80:                 syslog(LOG_ERR, "accept: %m");
   81: # else
   82:                 perror("accept");
   83: # endif
   84:                 cleanup(1);
   85:         }
   86: 
   87: # ifdef INTERNET
   88:         machine = ntohl(((struct sockaddr_in *) &sockstruct)->sin_addr.s_addr);
   89: # else
   90:         if (machine == 0)
   91:                 machine = gethostid();
   92: # endif
   93:         version = htonl((u_int32_t) HUNT_VERSION);
   94:         (void) write(newsock, (char *) &version, LONGLEN);
   95:         (void) read(newsock, (char *) &uid, LONGLEN);
   96:         uid = ntohl((unsigned long) uid);
   97:         (void) read(newsock, name, NAMELEN);
   98:         (void) read(newsock, &team, 1);
   99:         (void) read(newsock, (char *) &enter_status, LONGLEN);
  100:         enter_status = ntohl((unsigned long) enter_status);
  101:         (void) read(newsock, Ttyname, NAMELEN);
  102:         (void) read(newsock, (char *) &mode, sizeof mode);
  103:         mode = ntohl(mode);
  104: 
  105:         /*
  106:          * Turn off blocking I/O, so a slow or dead terminal won't stop
  107:          * the game.  All subsequent reads check how many bytes they read.
  108:          */
  109:         flags = fcntl(newsock, F_GETFL, 0);
  110:         flags |= O_NDELAY;
  111:         (void) fcntl(newsock, F_SETFL, flags);
  112: 
  113:         /*
  114:          * Make sure the name contains only printable characters
  115:          * since we use control characters for cursor control
  116:          * between driver and player processes
  117:          */
  118:         for (cp1 = cp2 = name; *cp1 != '\0'; cp1++)
  119:                 if (isprint((unsigned char)*cp1) || *cp1 == ' ')
  120:                         *cp2++ = *cp1;
  121:         *cp2 = '\0';
  122: 
  123: # ifdef INTERNET
  124:         if (mode == C_MESSAGE) {
  125:                 char  buf[BUFSIZ + 1];
  126:                 int   n;
  127: 
  128:                 if (team == ' ')
  129:                         (void) sprintf(buf, "%s: ", name);
  130:                 else
  131:                         (void) sprintf(buf, "%s[%c]: ", name, team);
  132:                 n = strlen(buf);
  133:                 for (pp = Player; pp < End_player; pp++) {
  134:                         cgoto(pp, HEIGHT, 0);
  135:                         outstr(pp, buf, n);
  136:                 }
  137:                 while ((n = read(newsock, buf, BUFSIZ)) > 0)
  138:                         for (pp = Player; pp < End_player; pp++)
  139:                                 outstr(pp, buf, n);
  140:                 for (pp = Player; pp < End_player; pp++) {
  141:                         ce(pp);
  142:                         sendcom(pp, REFRESH);
  143:                         sendcom(pp, READY, 0);
  144:                         (void) fflush(pp->p_output);
  145:                 }
  146:                 (void) close(newsock);
  147:                 return FALSE;
  148:         }
  149:         else
  150: # endif
  151: # ifdef MONITOR
  152:         if (mode == C_MONITOR)
  153:                 if (End_monitor < &Monitor[MAXMON]) {
  154:                         pp = End_monitor++;
  155:                         i = pp - Monitor + MAXPL + 3;
  156:                 } else {
  157:                         socklen = 0;
  158:                         (void) write(newsock, (char *) &socklen,
  159:                                 sizeof socklen);
  160:                         (void) close(newsock);
  161:                         return FALSE;
  162:                 }
  163:         else
  164: # endif
  165:                 if (End_player < &Player[MAXPL]) {
  166:                         pp = End_player++;
  167:                         i = pp - Player + 3;
  168:                 } else {
  169:                         socklen = 0;
  170:                         (void) write(newsock, (char *) &socklen,
  171:                                 sizeof socklen);
  172:                         (void) close(newsock);
  173:                         return FALSE;
  174:                 }
  175: 
  176: #ifdef MONITOR
  177:         if (mode == C_MONITOR && team == ' ')
  178:                 team = '*';
  179: #endif
  180:         pp->p_ident = get_ident(machine, uid, name, team);
  181:         pp->p_output = fdopen(newsock, "w");
  182:         pp->p_death[0] = '\0';
  183:         pp->p_fd = newsock;
  184:         fdset[i].fd = newsock;
  185:         fdset[i].events = POLLIN;
  186: 
  187:         pp->p_y = 0;
  188:         pp->p_x = 0;
  189: 
  190: # ifdef MONITOR
  191:         if (mode == C_MONITOR)
  192:                 stmonitor(pp);
  193:         else
  194: # endif
  195:                 stplayer(pp, enter_status);
  196:         return TRUE;
  197: }
  198: 
  199: # ifdef MONITOR
  200: void
  201: stmonitor(pp)
  202:         PLAYER *pp;
  203: {
  204:         int    line;
  205:         PLAYER *npp;
  206: 
  207:         memcpy(pp->p_maze, Maze, sizeof Maze);
  208: 
  209:         drawmaze(pp);
  210: 
  211:         (void) sprintf(Buf, "%5.5s%c%-10.10s %c", " ", stat_char(pp),
  212:                 pp->p_ident->i_name, pp->p_ident->i_team);
  213:         line = STAT_MON_ROW + 1 + (pp - Monitor);
  214:         for (npp = Player; npp < End_player; npp++) {
  215:                 cgoto(npp, line, STAT_NAME_COL);
  216:                 outstr(npp, Buf, STAT_NAME_LEN);
  217:         }
  218:         for (npp = Monitor; npp < End_monitor; npp++) {
  219:                 cgoto(npp, line, STAT_NAME_COL);
  220:                 outstr(npp, Buf, STAT_NAME_LEN);
  221:         }
  222: 
  223:         sendcom(pp, REFRESH);
  224:         sendcom(pp, READY, 0);
  225:         (void) fflush(pp->p_output);
  226: }
  227: # endif
  228: 
  229: void
  230: stplayer(newpp, enter_status)
  231:         PLAYER *newpp;
  232:         int    enter_status;
  233: {
  234:         int    x, y;
  235:         PLAYER *pp;
  236: 
  237:         Nplayer++;
  238: 
  239:         for (y = 0; y < UBOUND; y++)
  240:                 for (x = 0; x < WIDTH; x++)
  241:                         newpp->p_maze[y][x] = Maze[y][x];
  242:         for (     ; y < DBOUND; y++) {
  243:                 for (x = 0; x < LBOUND; x++)
  244:                         newpp->p_maze[y][x] = Maze[y][x];
  245:                 for (     ; x < RBOUND; x++)
  246:                         newpp->p_maze[y][x] = SPACE;
  247:                 for (     ; x < WIDTH;  x++)
  248:                         newpp->p_maze[y][x] = Maze[y][x];
  249:         }
  250:         for (     ; y < HEIGHT; y++)
  251:                 for (x = 0; x < WIDTH; x++)
  252:                         newpp->p_maze[y][x] = Maze[y][x];
  253: 
  254:         do {
  255:                 x = rand_num(WIDTH - 1) + 1;
  256:                 y = rand_num(HEIGHT - 1) + 1;
  257:         } while (Maze[y][x] != SPACE);
  258:         newpp->p_over = SPACE;
  259:         newpp->p_x = x;
  260:         newpp->p_y = y;
  261:         newpp->p_undershot = FALSE;
  262: 
  263: # ifdef FLY
  264:         if (enter_status == Q_FLY) {
  265:                 newpp->p_flying = rand_num(20);
  266:                 newpp->p_flyx = 2 * rand_num(6) - 5;
  267:                 newpp->p_flyy = 2 * rand_num(6) - 5;
  268:                 newpp->p_face = FLYER;
  269:         }
  270:         else
  271: # endif
  272:         {
  273:                 newpp->p_flying = -1;
  274:                 newpp->p_face = rand_dir();
  275:         }
  276:         newpp->p_damage = 0;
  277:         newpp->p_damcap = MAXDAM;
  278:         newpp->p_nchar = 0;
  279:         newpp->p_ncount = 0;
  280:         newpp->p_nexec = 0;
  281:         newpp->p_ammo = ISHOTS;
  282: # ifdef BOOTS
  283:         newpp->p_nboots = 0;
  284: # endif
  285:         if (enter_status == Q_SCAN) {
  286:                 newpp->p_scan = SCANLEN;
  287:                 newpp->p_cloak = 0;
  288:         }
  289:         else {
  290:                 newpp->p_scan = 0;
  291:                 newpp->p_cloak = CLOAKLEN;
  292:         }
  293:         newpp->p_ncshot = 0;
  294: 
  295:         do {
  296:                 x = rand_num(WIDTH - 1) + 1;
  297:                 y = rand_num(HEIGHT - 1) + 1;
  298:         } while (Maze[y][x] != SPACE);
  299:         Maze[y][x] = GMINE;
  300: # ifdef MONITOR
  301:         for (pp = Monitor; pp < End_monitor; pp++)
  302:                 check(pp, y, x);
  303: # endif
  304: 
  305:         do {
  306:                 x = rand_num(WIDTH - 1) + 1;
  307:                 y = rand_num(HEIGHT - 1) + 1;
  308:         } while (Maze[y][x] != SPACE);
  309:         Maze[y][x] = MINE;
  310: # ifdef MONITOR
  311:         for (pp = Monitor; pp < End_monitor; pp++)
  312:                 check(pp, y, x);
  313: # endif
  314: 
  315:         (void) sprintf(Buf, "%5.2f%c%-10.10s %c", newpp->p_ident->i_score,
  316:                 stat_char(newpp), newpp->p_ident->i_name,
  317:                 newpp->p_ident->i_team);
  318:         y = STAT_PLAY_ROW + 1 + (newpp - Player);
  319:         for (pp = Player; pp < End_player; pp++) {
  320:                 if (pp != newpp) {
  321:                         char smallbuf[10];
  322: 
  323:                         pp->p_ammo += NSHOTS;
  324:                         newpp->p_ammo += NSHOTS;
  325:                         cgoto(pp, y, STAT_NAME_COL);
  326:                         outstr(pp, Buf, STAT_NAME_LEN);
  327:                         (void) sprintf(smallbuf, "%3d", pp->p_ammo);
  328:                         cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
  329:                         outstr(pp, smallbuf, 3);
  330:                 }
  331:         }
  332: # ifdef MONITOR
  333:         for (pp = Monitor; pp < End_monitor; pp++) {
  334:                 cgoto(pp, y, STAT_NAME_COL);
  335:                 outstr(pp, Buf, STAT_NAME_LEN);
  336:         }
  337: # endif
  338: 
  339:         drawmaze(newpp);
  340:         drawplayer(newpp, TRUE);
  341:         look(newpp);
  342: # ifdef FLY
  343:         if (enter_status == Q_FLY)
  344:                 /* Make sure that the position you enter in will be erased */
  345:                 showexpl(newpp->p_y, newpp->p_x, FLYER);
  346: # endif
  347:         sendcom(newpp, REFRESH);
  348:         sendcom(newpp, READY, 0);
  349:         (void) fflush(newpp->p_output);
  350: }
  351: 
  352: /*
  353:  * rand_dir:
  354:  *      Return a random direction
  355:  */
  356: int
  357: rand_dir()
  358: {
  359:         switch (rand_num(4)) {
  360:           case 0:
  361:                 return LEFTS;
  362:           case 1:
  363:                 return RIGHT;
  364:           case 2:
  365:                 return BELOW;
  366:           case 3:
  367:                 return ABOVE;
  368:         }
  369:         /* NOTREACHED */
  370:         return(-1);
  371: }
  372: 
  373: /*
  374:  * get_ident:
  375:  *      Get the score structure of a player
  376:  */
  377: IDENT *
  378: get_ident(machine, uid, name, team)
  379:         u_long machine;
  380:         u_long uid;
  381:         const char     *name;
  382:         char   team;
  383: {
  384:         IDENT          *ip;
  385:         static IDENT   punt;
  386: 
  387:         for (ip = Scores; ip != NULL; ip = ip->i_next)
  388:                 if ((unsigned long)ip->i_machine == machine
  389:                 &&  (unsigned long)ip->i_uid == uid
  390:                 &&  ip->i_team == team
  391:                 &&  strncmp(ip->i_name, name, NAMELEN) == 0)
  392:                         break;
  393: 
  394:         if (ip != NULL) {
  395:                 if (ip->i_entries < SCOREDECAY)
  396:                         ip->i_entries++;
  397:                 else
  398:                         ip->i_kills = (ip->i_kills * (SCOREDECAY - 1))
  399:                                 / SCOREDECAY;
  400:                 ip->i_score = ip->i_kills / (double) ip->i_entries;
  401:         }
  402:         else {
  403:                 ip = (IDENT *) malloc(sizeof (IDENT));
  404:                 if (ip == NULL) {
  405:                         /* Fourth down, time to punt */
  406:                         ip = &punt;
  407:                 }
  408:                 ip->i_machine = machine;
  409:                 ip->i_team = team;
  410:                 ip->i_uid = uid;
  411:                 strncpy(ip->i_name, name, NAMELEN);
  412:                 ip->i_kills = 0;
  413:                 ip->i_entries = 1;
  414:                 ip->i_score = 0;
  415:                 ip->i_absorbed = 0;
  416:                 ip->i_faced = 0;
  417:                 ip->i_shot = 0;
  418:                 ip->i_robbed = 0;
  419:                 ip->i_slime = 0;
  420:                 ip->i_missed = 0;
  421:                 ip->i_ducked = 0;
  422:                 ip->i_gkills = ip->i_bkills = ip->i_deaths = 0;
  423:                 ip->i_stillb = ip->i_saved = 0;
  424:                 ip->i_next = Scores;
  425:                 Scores = ip;
  426:         }
  427: 
  428:         return ip;
  429: }
Syntax (Markdown)