1: /* 2: * Hunt 3: * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold 4: * San Francisco, California 5: * 6: * Copyright (c) 1985 Regents of the University of California. 7: * All rights reserved. The Berkeley software License Agreement 8: * specifies the terms and conditions for redistribution. 9: * 10: * @(#) answer.c 1.1 (2.11BSD) 96/7/10 11: */ 12: 13: # include "hunt.h" 14: # include <errno.h> 15: # include <unistd.h> /* for gethostid() */ 16: 17: # define MAXPERMACH 3 /* Max player/monitor per machine */ 18: 19: static char Ttyname[NAMELEN]; 20: 21: answer() 22: { 23: register PLAYER *pp; 24: register int newsock; 25: register FILE *tmpfd; 26: # ifdef MONITOR 27: static FLAG monitor; 28: # endif MONITOR 29: static char name[NAMELEN]; 30: static int socklen; 31: static u_long machine; 32: static u_long uid; 33: static SOCKET sockstruct; 34: # ifdef OLDIPC 35: extern SOCKET Daemon; 36: # endif OLDIPC 37: 38: # ifdef INTERNET 39: socklen = sizeof sockstruct; 40: # else 41: socklen = sizeof sockstruct - 1; 42: # endif INTERNET 43: errno = 0; 44: # ifndef OLDIPC 45: if ((newsock = accept(Socket, &sockstruct, &socklen)) < 0) 46: # else OLDIPC 47: if (accept(Socket, &sockstruct) < 0) 48: # endif OLDIPC 49: { 50: if (errno == EINTR) 51: return; 52: perror("accept"); 53: cleanup(1); 54: } 55: # ifdef OLDIPC 56: newsock = Socket; 57: Socket = socket(SOCK_STREAM, 0, (struct sockaddr *) &Daemon, 58: SO_ACCEPTCONN); 59: if (Socket < 0) { 60: perror("new accept socket"); 61: cleanup(1); 62: } 63: Sock_mask = (1 << Socket); 64: Fds_mask |= Sock_mask; 65: if (Socket >= Num_fds) 66: Num_fds = Socket + 1; 67: # endif OLDIPC 68: 69: tmpfd = fdopen(newsock, "w"); 70: 71: # ifdef INTERNET 72: machine = ntohl(((struct sockaddr_in *) &sockstruct)->sin_addr.s_addr); 73: # else INTERNET 74: if (machine == 0) 75: machine = gethostid(); 76: # endif INTERNET 77: (void) putw(getpid(), tmpfd); 78: (void) read(newsock, (char *) &uid, sizeof uid); 79: uid = ntohl(uid); 80: (void) read(newsock, name, NAMELEN); 81: (void) read(newsock, Ttyname, NAMELEN); 82: # ifdef MONITOR 83: (void) read(newsock, (char *) &monitor, sizeof monitor); 84: # endif MONITOR 85: 86: if (reached_limit(machine)) { 87: socklen = 0; 88: (void) write(newsock, (char *) &socklen, sizeof socklen); 89: (void) close(newsock); 90: # ifdef OLDIPC 91: Fds_mask &= ~(1 << newsock); 92: # endif OLDIPC 93: return; 94: } 95: 96: # ifdef MONITOR 97: if (monitor) 98: if (End_monitor < &Monitor[MAXMON]) 99: pp = End_monitor++; 100: else { 101: socklen = 0; 102: (void) write(newsock, (char *) &socklen, 103: sizeof socklen); 104: (void) close(newsock); 105: return; 106: } 107: else 108: # endif MONITOR 109: if (End_player < &Player[MAXPL]) 110: pp = End_player++; 111: else { 112: socklen = 0; 113: (void) write(newsock, (char *) &socklen, 114: sizeof socklen); 115: (void) close(newsock); 116: return; 117: } 118: 119: pp->p_ident = get_ident(machine, uid, name); 120: pp->p_output = tmpfd; 121: pp->p_death[0] = '\0'; 122: pp->p_fd = newsock; 123: pp->p_mask = (1 << pp->p_fd); 124: # ifndef OLDIPC 125: Fds_mask |= pp->p_mask; 126: if (pp->p_fd >= Num_fds) 127: Num_fds = pp->p_fd + 1; 128: # endif OLDIPC 129: 130: pp->p_y = 0; 131: pp->p_x = 0; 132: 133: # ifdef MONITOR 134: if (monitor) 135: stmonitor(pp); 136: else 137: # endif MONITOR 138: stplayer(pp); 139: } 140: 141: # ifdef MONITOR 142: stmonitor(pp) 143: register PLAYER *pp; 144: { 145: register int line; 146: register PLAYER *npp; 147: 148: bcopy((char *) Maze, (char *) pp->p_maze, sizeof Maze); 149: 150: drawmaze(pp); 151: 152: (void) sprintf(Buf, "%5.5s%c%-10.10s", " ", stat_char(pp), 153: pp->p_ident->i_name); 154: line = STAT_MON_ROW + 1 + (pp - Monitor); 155: for (npp = Player; npp < End_player; npp++) { 156: cgoto(npp, line, STAT_NAME_COL); 157: outstr(npp, Buf, STAT_NAME_LEN); 158: } 159: for (npp = Monitor; npp < End_monitor; npp++) { 160: cgoto(npp, line, STAT_NAME_COL); 161: outstr(npp, Buf, STAT_NAME_LEN); 162: } 163: 164: sendcom(pp, REFRESH); 165: sendcom(pp, READY, 0); 166: (void) fflush(pp->p_output); 167: } 168: # endif MONITOR 169: 170: stplayer(newpp) 171: register PLAYER *newpp; 172: { 173: register int x, y; 174: register PLAYER *pp; 175: 176: Nplayer++; 177: 178: for (y = 0; y < UBOUND; y++) 179: for (x = 0; x < WIDTH; x++) 180: newpp->p_maze[y][x] = Maze[y][x]; 181: for ( ; y < DBOUND; y++) { 182: for (x = 0; x < LBOUND; x++) 183: newpp->p_maze[y][x] = Maze[y][x]; 184: for ( ; x < RBOUND; x++) 185: newpp->p_maze[y][x] = SPACE; 186: for ( ; x < WIDTH; x++) 187: newpp->p_maze[y][x] = Maze[y][x]; 188: } 189: for ( ; y < HEIGHT; y++) 190: for (x = 0; x < WIDTH; x++) 191: newpp->p_maze[y][x] = Maze[y][x]; 192: 193: do { 194: x = rand_num(WIDTH - 1) + 1; 195: y = rand_num(HEIGHT - 1) + 1; 196: } while (Maze[y][x] != SPACE); 197: newpp->p_over = SPACE; 198: newpp->p_x = x; 199: newpp->p_y = y; 200: newpp->p_undershot = FALSE; 201: 202: # ifdef START_FLYING 203: /* This is only for debugging */ 204: newpp->p_flying = rand_num(20); 205: newpp->p_flyx = 2 * rand_num(6) - 5; 206: newpp->p_flyy = 2 * rand_num(6) - 5; 207: newpp->p_face = FLYER; 208: # else START_FLYING 209: newpp->p_flying = -1; 210: rand_face(newpp); 211: # endif START_FLYING 212: newpp->p_damage = 0; 213: newpp->p_damcap = MAXDAM; 214: newpp->p_nchar = 0; 215: newpp->p_ncount = 0; 216: newpp->p_nexec = 0; 217: newpp->p_ammo = ISHOTS; 218: newpp->p_scan = -1; 219: newpp->p_cloak = CLOAKLEN; 220: newpp->p_ncshot = 0; 221: 222: do { 223: x = rand_num(WIDTH - 1) + 1; 224: y = rand_num(HEIGHT - 1) + 1; 225: } while (Maze[y][x] != SPACE); 226: Maze[y][x] = GMINE; 227: # ifdef MONITOR 228: for (pp = Monitor; pp < End_monitor; pp++) 229: check(pp, y, x); 230: # endif MONITOR 231: 232: do { 233: x = rand_num(WIDTH - 1) + 1; 234: y = rand_num(HEIGHT - 1) + 1; 235: } while (Maze[y][x] != SPACE); 236: Maze[y][x] = MINE; 237: # ifdef MONITOR 238: for (pp = Monitor; pp < End_monitor; pp++) 239: check(pp, y, x); 240: # endif MONITOR 241: 242: (void) sprintf(Buf, "%5.2f%c%-10.10s", newpp->p_ident->i_score, 243: stat_char(newpp), newpp->p_ident->i_name); 244: y = STAT_PLAY_ROW + 1 + (newpp - Player); 245: for (pp = Player; pp < End_player; pp++) { 246: if (pp != newpp) { 247: char smallbuf[10]; 248: 249: pp->p_ammo += NSHOTS; 250: newpp->p_ammo += NSHOTS; 251: cgoto(pp, y, STAT_NAME_COL); 252: outstr(pp, Buf, STAT_NAME_LEN); 253: (void) sprintf(smallbuf, "%3d", pp->p_ammo); 254: cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL); 255: outstr(pp, smallbuf, 3); 256: } 257: } 258: # ifdef MONITOR 259: for (pp = Monitor; pp < End_monitor; pp++) { 260: cgoto(pp, y, STAT_NAME_COL); 261: outstr(pp, Buf, STAT_NAME_LEN); 262: } 263: # endif MONITOR 264: 265: drawmaze(newpp); 266: drawplayer(newpp, TRUE); 267: look(newpp); 268: # ifdef START_FLYING 269: /* Make sure that the position you enter in will be erased */ 270: showexpl(newpp->p_y, newpp->p_x, FLYER); 271: # endif START_FLYING 272: sendcom(newpp, REFRESH); 273: sendcom(newpp, READY, 0); 274: (void) fflush(newpp->p_output); 275: } 276: 277: /* 278: * rand_face: 279: * Give the player a random facing direction 280: */ 281: rand_face(pp) 282: register PLAYER *pp; 283: { 284: switch (rand_num(4)) { 285: case 0: 286: pp->p_face = LEFTS; 287: break; 288: case 1: 289: pp->p_face = RIGHT; 290: break; 291: case 2: 292: pp->p_face = BELOW; 293: break; 294: case 3: 295: pp->p_face = ABOVE; 296: break; 297: } 298: } 299: 300: /* 301: * get_ident: 302: * Get the score structure of a player 303: */ 304: IDENT * 305: get_ident(machine, uid, name) 306: u_long machine; 307: u_long uid; 308: char *name; 309: { 310: register IDENT *ip; 311: static IDENT punt; 312: 313: for (ip = Scores; ip != NULL; ip = ip->i_next) 314: if (ip->i_machine == machine && ip->i_uid == uid && 315: strncmp(ip->i_name, name, NAMELEN) == 0) 316: break; 317: 318: if (ip != NULL) { 319: ip->i_entries++; 320: ip->i_score = ip->i_kills / (double) ip->i_entries; 321: } 322: else { 323: ip = (IDENT *) malloc(sizeof (IDENT)); 324: if (ip == NULL) { 325: /* Fourth down, time to punt */ 326: ip = &punt; 327: } 328: ip->i_machine = machine; 329: ip->i_uid = uid; 330: strncpy(ip->i_name, name, NAMELEN); 331: ip->i_kills = 0; 332: ip->i_entries = 1; 333: ip->i_score = 0; 334: ip->i_next = Scores; 335: Scores = ip; 336: } 337: 338: return ip; 339: } 340: 341: /* 342: * reached_limit: 343: * Returns whether the limit of x persons per machine has been reached 344: */ 345: reached_limit(machine) 346: u_long machine; 347: { 348: register PLAYER *pp; 349: register int count; 350: 351: count = 0; 352: for (pp = Player; pp < End_player; pp++) 353: if (pp->p_ident->i_machine == machine) 354: count++; 355: for (pp = Monitor; pp < End_monitor; pp++) 356: if (pp->p_ident->i_machine == machine) 357: count++; 358: return count >= MAXPERMACH; 359: }