/* * Hunt * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold * San Francisco, California * * Copyright (c) 1985 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#) answer.c 1.1 (2.11BSD) 96/7/10 */ # include "hunt.h" # include # include /* for gethostid() */ # define MAXPERMACH 3 /* Max player/monitor per machine */ static char Ttyname[NAMELEN]; answer() { register PLAYER *pp; register int newsock; register FILE *tmpfd; # ifdef MONITOR static FLAG monitor; # endif MONITOR static char name[NAMELEN]; static int socklen; static u_long machine; static u_long uid; static SOCKET sockstruct; # ifdef OLDIPC extern SOCKET Daemon; # endif OLDIPC # ifdef INTERNET socklen = sizeof sockstruct; # else socklen = sizeof sockstruct - 1; # endif INTERNET errno = 0; # ifndef OLDIPC if ((newsock = accept(Socket, &sockstruct, &socklen)) < 0) # else OLDIPC if (accept(Socket, &sockstruct) < 0) # endif OLDIPC { if (errno == EINTR) return; perror("accept"); cleanup(1); } # ifdef OLDIPC newsock = Socket; Socket = socket(SOCK_STREAM, 0, (struct sockaddr *) &Daemon, SO_ACCEPTCONN); if (Socket < 0) { perror("new accept socket"); cleanup(1); } Sock_mask = (1 << Socket); Fds_mask |= Sock_mask; if (Socket >= Num_fds) Num_fds = Socket + 1; # endif OLDIPC tmpfd = fdopen(newsock, "w"); # ifdef INTERNET machine = ntohl(((struct sockaddr_in *) &sockstruct)->sin_addr.s_addr); # else INTERNET if (machine == 0) machine = gethostid(); # endif INTERNET (void) putw(getpid(), tmpfd); (void) read(newsock, (char *) &uid, sizeof uid); uid = ntohl(uid); (void) read(newsock, name, NAMELEN); (void) read(newsock, Ttyname, NAMELEN); # ifdef MONITOR (void) read(newsock, (char *) &monitor, sizeof monitor); # endif MONITOR if (reached_limit(machine)) { socklen = 0; (void) write(newsock, (char *) &socklen, sizeof socklen); (void) close(newsock); # ifdef OLDIPC Fds_mask &= ~(1 << newsock); # endif OLDIPC return; } # ifdef MONITOR if (monitor) if (End_monitor < &Monitor[MAXMON]) pp = End_monitor++; else { socklen = 0; (void) write(newsock, (char *) &socklen, sizeof socklen); (void) close(newsock); return; } else # endif MONITOR if (End_player < &Player[MAXPL]) pp = End_player++; else { socklen = 0; (void) write(newsock, (char *) &socklen, sizeof socklen); (void) close(newsock); return; } pp->p_ident = get_ident(machine, uid, name); pp->p_output = tmpfd; pp->p_death[0] = '\0'; pp->p_fd = newsock; pp->p_mask = (1 << pp->p_fd); # ifndef OLDIPC Fds_mask |= pp->p_mask; if (pp->p_fd >= Num_fds) Num_fds = pp->p_fd + 1; # endif OLDIPC pp->p_y = 0; pp->p_x = 0; # ifdef MONITOR if (monitor) stmonitor(pp); else # endif MONITOR stplayer(pp); } # ifdef MONITOR stmonitor(pp) register PLAYER *pp; { register int line; register PLAYER *npp; bcopy((char *) Maze, (char *) pp->p_maze, sizeof Maze); drawmaze(pp); (void) sprintf(Buf, "%5.5s%c%-10.10s", " ", stat_char(pp), pp->p_ident->i_name); line = STAT_MON_ROW + 1 + (pp - Monitor); for (npp = Player; npp < End_player; npp++) { cgoto(npp, line, STAT_NAME_COL); outstr(npp, Buf, STAT_NAME_LEN); } for (npp = Monitor; npp < End_monitor; npp++) { cgoto(npp, line, STAT_NAME_COL); outstr(npp, Buf, STAT_NAME_LEN); } sendcom(pp, REFRESH); sendcom(pp, READY, 0); (void) fflush(pp->p_output); } # endif MONITOR stplayer(newpp) register PLAYER *newpp; { register int x, y; register PLAYER *pp; Nplayer++; for (y = 0; y < UBOUND; y++) for (x = 0; x < WIDTH; x++) newpp->p_maze[y][x] = Maze[y][x]; for ( ; y < DBOUND; y++) { for (x = 0; x < LBOUND; x++) newpp->p_maze[y][x] = Maze[y][x]; for ( ; x < RBOUND; x++) newpp->p_maze[y][x] = SPACE; for ( ; x < WIDTH; x++) newpp->p_maze[y][x] = Maze[y][x]; } for ( ; y < HEIGHT; y++) for (x = 0; x < WIDTH; x++) newpp->p_maze[y][x] = Maze[y][x]; do { x = rand_num(WIDTH - 1) + 1; y = rand_num(HEIGHT - 1) + 1; } while (Maze[y][x] != SPACE); newpp->p_over = SPACE; newpp->p_x = x; newpp->p_y = y; newpp->p_undershot = FALSE; # ifdef START_FLYING /* This is only for debugging */ newpp->p_flying = rand_num(20); newpp->p_flyx = 2 * rand_num(6) - 5; newpp->p_flyy = 2 * rand_num(6) - 5; newpp->p_face = FLYER; # else START_FLYING newpp->p_flying = -1; rand_face(newpp); # endif START_FLYING newpp->p_damage = 0; newpp->p_damcap = MAXDAM; newpp->p_nchar = 0; newpp->p_ncount = 0; newpp->p_nexec = 0; newpp->p_ammo = ISHOTS; newpp->p_scan = -1; newpp->p_cloak = CLOAKLEN; newpp->p_ncshot = 0; do { x = rand_num(WIDTH - 1) + 1; y = rand_num(HEIGHT - 1) + 1; } while (Maze[y][x] != SPACE); Maze[y][x] = GMINE; # ifdef MONITOR for (pp = Monitor; pp < End_monitor; pp++) check(pp, y, x); # endif MONITOR do { x = rand_num(WIDTH - 1) + 1; y = rand_num(HEIGHT - 1) + 1; } while (Maze[y][x] != SPACE); Maze[y][x] = MINE; # ifdef MONITOR for (pp = Monitor; pp < End_monitor; pp++) check(pp, y, x); # endif MONITOR (void) sprintf(Buf, "%5.2f%c%-10.10s", newpp->p_ident->i_score, stat_char(newpp), newpp->p_ident->i_name); y = STAT_PLAY_ROW + 1 + (newpp - Player); for (pp = Player; pp < End_player; pp++) { if (pp != newpp) { char smallbuf[10]; pp->p_ammo += NSHOTS; newpp->p_ammo += NSHOTS; cgoto(pp, y, STAT_NAME_COL); outstr(pp, Buf, STAT_NAME_LEN); (void) sprintf(smallbuf, "%3d", pp->p_ammo); cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL); outstr(pp, smallbuf, 3); } } # ifdef MONITOR for (pp = Monitor; pp < End_monitor; pp++) { cgoto(pp, y, STAT_NAME_COL); outstr(pp, Buf, STAT_NAME_LEN); } # endif MONITOR drawmaze(newpp); drawplayer(newpp, TRUE); look(newpp); # ifdef START_FLYING /* Make sure that the position you enter in will be erased */ showexpl(newpp->p_y, newpp->p_x, FLYER); # endif START_FLYING sendcom(newpp, REFRESH); sendcom(newpp, READY, 0); (void) fflush(newpp->p_output); } /* * rand_face: * Give the player a random facing direction */ rand_face(pp) register PLAYER *pp; { switch (rand_num(4)) { case 0: pp->p_face = LEFTS; break; case 1: pp->p_face = RIGHT; break; case 2: pp->p_face = BELOW; break; case 3: pp->p_face = ABOVE; break; } } /* * get_ident: * Get the score structure of a player */ IDENT * get_ident(machine, uid, name) u_long machine; u_long uid; char *name; { register IDENT *ip; static IDENT punt; for (ip = Scores; ip != NULL; ip = ip->i_next) if (ip->i_machine == machine && ip->i_uid == uid && strncmp(ip->i_name, name, NAMELEN) == 0) break; if (ip != NULL) { ip->i_entries++; ip->i_score = ip->i_kills / (double) ip->i_entries; } else { ip = (IDENT *) malloc(sizeof (IDENT)); if (ip == NULL) { /* Fourth down, time to punt */ ip = &punt; } ip->i_machine = machine; ip->i_uid = uid; strncpy(ip->i_name, name, NAMELEN); ip->i_kills = 0; ip->i_entries = 1; ip->i_score = 0; ip->i_next = Scores; Scores = ip; } return ip; } /* * reached_limit: * Returns whether the limit of x persons per machine has been reached */ reached_limit(machine) u_long machine; { register PLAYER *pp; register int count; count = 0; for (pp = Player; pp < End_player; pp++) if (pp->p_ident->i_machine == machine) count++; for (pp = Monitor; pp < End_monitor; pp++) if (pp->p_ident->i_machine == machine) count++; return count >= MAXPERMACH; }