1*1182a44cSrillig /* $NetBSD: answer.c,v 1.24 2021/05/02 12:50:45 rillig Exp $ */
24052d13dSmrg /*
311967175Swiz * Copyright (c) 1983-2003, Regents of the University of California.
411967175Swiz * All rights reserved.
511967175Swiz *
611967175Swiz * Redistribution and use in source and binary forms, with or without
711967175Swiz * modification, are permitted provided that the following conditions are
811967175Swiz * met:
911967175Swiz *
1011967175Swiz * + Redistributions of source code must retain the above copyright
1111967175Swiz * notice, this list of conditions and the following disclaimer.
1211967175Swiz * + Redistributions in binary form must reproduce the above copyright
1311967175Swiz * notice, this list of conditions and the following disclaimer in the
1411967175Swiz * documentation and/or other materials provided with the distribution.
1511967175Swiz * + Neither the name of the University of California, San Francisco nor
1611967175Swiz * the names of its contributors may be used to endorse or promote
1711967175Swiz * products derived from this software without specific prior written
1811967175Swiz * permission.
1911967175Swiz *
2011967175Swiz * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
2111967175Swiz * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2211967175Swiz * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
2311967175Swiz * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2411967175Swiz * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2511967175Swiz * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2611967175Swiz * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2711967175Swiz * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2811967175Swiz * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2911967175Swiz * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3011967175Swiz * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
314052d13dSmrg */
324052d13dSmrg
33544a5e33Slukem #include <sys/cdefs.h>
34544a5e33Slukem #ifndef lint
35*1182a44cSrillig __RCSID("$NetBSD: answer.c,v 1.24 2021/05/02 12:50:45 rillig Exp $");
36544a5e33Slukem #endif /* not lint */
37544a5e33Slukem
38f0ab07d6Sdholland #include <sys/types.h>
39f0ab07d6Sdholland #include <sys/socket.h>
409e2af583Sdholland #include <netinet/in.h>
414052d13dSmrg #include <ctype.h>
424052d13dSmrg #include <errno.h>
434052d13dSmrg #include <fcntl.h>
44544a5e33Slukem #include <stdlib.h>
45544a5e33Slukem #include <unistd.h>
469e2af583Sdholland #include <assert.h>
47544a5e33Slukem #include "hunt.h"
484052d13dSmrg
494052d13dSmrg #define SCOREDECAY 15
504052d13dSmrg
51c560d1b1Sdholland static char Ttyname[WIRE_NAMELEN];
524052d13dSmrg
53c560d1b1Sdholland static IDENT *get_ident(uint32_t, uint32_t, const char *, char);
5475b3905dSdholland static void stmonitor(PLAYER *);
5575b3905dSdholland static void stplayer(PLAYER *, int);
5675b3905dSdholland
579cdcb5fdSdholland bool
answer(void)58fbca3d8cSdholland answer(void)
594052d13dSmrg {
60544a5e33Slukem PLAYER *pp;
61544a5e33Slukem int newsock;
62c560d1b1Sdholland static uint32_t mode;
63c560d1b1Sdholland static char name[WIRE_NAMELEN];
644052d13dSmrg static char team;
65c560d1b1Sdholland static int32_t enter_status;
660c37c63eSmrg static socklen_t socklen;
67733dc966Sdholland static uint32_t machine;
68733dc966Sdholland static uint32_t uid;
699e2af583Sdholland static struct sockaddr_storage newaddr;
70544a5e33Slukem char *cp1, *cp2;
714052d13dSmrg int flags;
729ac5061bSdholland uint32_t version;
7367ba9a58Smycroft int i;
744052d13dSmrg
759e2af583Sdholland socklen = sizeof(newaddr);
769e2af583Sdholland newsock = accept(huntsock, (struct sockaddr *)&newaddr, &socklen);
779e2af583Sdholland if (newsock < 0) {
784052d13dSmrg if (errno == EINTR)
7937a43147Sdholland return false;
80865e0d64Sdholland complain(LOG_ERR, "accept");
814052d13dSmrg cleanup(1);
824052d13dSmrg }
834052d13dSmrg
849e2af583Sdholland /*
859e2af583Sdholland * XXX this is pretty bollocks
869e2af583Sdholland */
879e2af583Sdholland switch (newaddr.ss_family) {
889e2af583Sdholland case AF_INET:
899e2af583Sdholland machine = ((struct sockaddr_in *)&newaddr)->sin_addr.s_addr;
909e2af583Sdholland machine = ntohl(machine);
919e2af583Sdholland break;
929e2af583Sdholland case AF_INET6:
939e2af583Sdholland {
949e2af583Sdholland struct sockaddr_in6 *sin6;
959e2af583Sdholland
969e2af583Sdholland sin6 = (struct sockaddr_in6 *)&newaddr;
979e2af583Sdholland assert(sizeof(sin6->sin6_addr.s6_addr) >
989e2af583Sdholland sizeof(machine));
999e2af583Sdholland memcpy(&machine, sin6->sin6_addr.s6_addr,
1009e2af583Sdholland sizeof(machine));
1019e2af583Sdholland }
1029e2af583Sdholland break;
1039e2af583Sdholland case AF_UNIX:
1044052d13dSmrg machine = gethostid();
1059e2af583Sdholland break;
1069e2af583Sdholland default:
1079e2af583Sdholland machine = 0; /* ? */
1089e2af583Sdholland break;
1099e2af583Sdholland }
1109e2af583Sdholland
1119ac5061bSdholland version = htonl((uint32_t) HUNT_VERSION);
112c560d1b1Sdholland (void) write(newsock, &version, sizeof(version));
113c560d1b1Sdholland (void) read(newsock, &uid, sizeof(uid));
114733dc966Sdholland uid = ntohl(uid);
115c560d1b1Sdholland (void) read(newsock, name, sizeof(name));
1164052d13dSmrg (void) read(newsock, &team, 1);
117c560d1b1Sdholland (void) read(newsock, &enter_status, sizeof(enter_status));
118c560d1b1Sdholland enter_status = ntohl(enter_status);
119c560d1b1Sdholland (void) read(newsock, Ttyname, sizeof(Ttyname));
120c560d1b1Sdholland (void) read(newsock, &mode, sizeof(mode));
1214052d13dSmrg mode = ntohl(mode);
1224052d13dSmrg
1234052d13dSmrg /*
1244c08f5f9Sdholland * Ensure null termination.
1254c08f5f9Sdholland */
1264c08f5f9Sdholland name[sizeof(name)-1] = '\0';
1274c08f5f9Sdholland Ttyname[sizeof(Ttyname)-1] = '\0';
1284c08f5f9Sdholland
1294c08f5f9Sdholland /*
1304052d13dSmrg * Turn off blocking I/O, so a slow or dead terminal won't stop
1314052d13dSmrg * the game. All subsequent reads check how many bytes they read.
1324052d13dSmrg */
1334052d13dSmrg flags = fcntl(newsock, F_GETFL, 0);
1344052d13dSmrg flags |= O_NDELAY;
1354052d13dSmrg (void) fcntl(newsock, F_SETFL, flags);
1364052d13dSmrg
1374052d13dSmrg /*
1384052d13dSmrg * Make sure the name contains only printable characters
1394052d13dSmrg * since we use control characters for cursor control
1404052d13dSmrg * between driver and player processes
1414052d13dSmrg */
1424052d13dSmrg for (cp1 = cp2 = name; *cp1 != '\0'; cp1++)
14349f7d8a9Sdsl if (isprint((unsigned char)*cp1) || *cp1 == ' ')
1444052d13dSmrg *cp2++ = *cp1;
1454052d13dSmrg *cp2 = '\0';
1464052d13dSmrg
1474052d13dSmrg if (mode == C_MESSAGE) {
1484052d13dSmrg char buf[BUFSIZ + 1];
1494052d13dSmrg int n;
1504052d13dSmrg
1514052d13dSmrg if (team == ' ')
1520ed1b742Sdholland (void) snprintf(buf, sizeof(buf), "%s: ", name);
1534052d13dSmrg else
1540ed1b742Sdholland (void) snprintf(buf, sizeof(buf), "%s[%c]: ", name,
1550ed1b742Sdholland team);
1564052d13dSmrg n = strlen(buf);
1574052d13dSmrg for (pp = Player; pp < End_player; pp++) {
1584052d13dSmrg cgoto(pp, HEIGHT, 0);
1594052d13dSmrg outstr(pp, buf, n);
1604052d13dSmrg }
1614052d13dSmrg while ((n = read(newsock, buf, BUFSIZ)) > 0)
1624052d13dSmrg for (pp = Player; pp < End_player; pp++)
1634052d13dSmrg outstr(pp, buf, n);
1644052d13dSmrg for (pp = Player; pp < End_player; pp++) {
1654052d13dSmrg ce(pp);
1664052d13dSmrg sendcom(pp, REFRESH);
1674052d13dSmrg sendcom(pp, READY, 0);
1684052d13dSmrg (void) fflush(pp->p_output);
1694052d13dSmrg }
1704052d13dSmrg (void) close(newsock);
17137a43147Sdholland return false;
1724052d13dSmrg }
1734052d13dSmrg else
1744052d13dSmrg #ifdef MONITOR
1754052d13dSmrg if (mode == C_MONITOR)
17667ba9a58Smycroft if (End_monitor < &Monitor[MAXMON]) {
1774052d13dSmrg pp = End_monitor++;
17867ba9a58Smycroft i = pp - Monitor + MAXPL + 3;
17967ba9a58Smycroft } else {
1804052d13dSmrg socklen = 0;
1816ffae662Sdholland (void) write(newsock, &socklen,
1824052d13dSmrg sizeof socklen);
1834052d13dSmrg (void) close(newsock);
18437a43147Sdholland return false;
1854052d13dSmrg }
1864052d13dSmrg else
1874052d13dSmrg #endif
18867ba9a58Smycroft if (End_player < &Player[MAXPL]) {
1894052d13dSmrg pp = End_player++;
19067ba9a58Smycroft i = pp - Player + 3;
19167ba9a58Smycroft } else {
1924052d13dSmrg socklen = 0;
1936ffae662Sdholland (void) write(newsock, &socklen,
1944052d13dSmrg sizeof socklen);
1954052d13dSmrg (void) close(newsock);
19637a43147Sdholland return false;
1974052d13dSmrg }
1984052d13dSmrg
1994052d13dSmrg #ifdef MONITOR
2004052d13dSmrg if (mode == C_MONITOR && team == ' ')
2014052d13dSmrg team = '*';
2024052d13dSmrg #endif
2034052d13dSmrg pp->p_ident = get_ident(machine, uid, name, team);
2044052d13dSmrg pp->p_output = fdopen(newsock, "w");
2054052d13dSmrg pp->p_death[0] = '\0';
2064052d13dSmrg pp->p_fd = newsock;
20767ba9a58Smycroft fdset[i].fd = newsock;
20867ba9a58Smycroft fdset[i].events = POLLIN;
2094052d13dSmrg
2104052d13dSmrg pp->p_y = 0;
2114052d13dSmrg pp->p_x = 0;
2124052d13dSmrg
2134052d13dSmrg #ifdef MONITOR
2144052d13dSmrg if (mode == C_MONITOR)
2154052d13dSmrg stmonitor(pp);
2164052d13dSmrg else
2174052d13dSmrg #endif
2184052d13dSmrg stplayer(pp, enter_status);
21937a43147Sdholland return true;
2204052d13dSmrg }
2214052d13dSmrg
2224052d13dSmrg #ifdef MONITOR
22375b3905dSdholland static void
stmonitor(PLAYER * pp)224fbca3d8cSdholland stmonitor(PLAYER *pp)
2254052d13dSmrg {
226544a5e33Slukem int line;
227544a5e33Slukem PLAYER *npp;
2284052d13dSmrg
2294052d13dSmrg memcpy(pp->p_maze, Maze, sizeof Maze);
2304052d13dSmrg
2314052d13dSmrg drawmaze(pp);
2324052d13dSmrg
2330ed1b742Sdholland (void) snprintf(Buf, sizeof(Buf), "%5.5s%c%-10.10s %c", " ",
2340ed1b742Sdholland stat_char(pp),
2354052d13dSmrg pp->p_ident->i_name, pp->p_ident->i_team);
2364052d13dSmrg line = STAT_MON_ROW + 1 + (pp - Monitor);
2374052d13dSmrg for (npp = Player; npp < End_player; npp++) {
2384052d13dSmrg cgoto(npp, line, STAT_NAME_COL);
2394052d13dSmrg outstr(npp, Buf, STAT_NAME_LEN);
2404052d13dSmrg }
2414052d13dSmrg for (npp = Monitor; npp < End_monitor; npp++) {
2424052d13dSmrg cgoto(npp, line, STAT_NAME_COL);
2434052d13dSmrg outstr(npp, Buf, STAT_NAME_LEN);
2444052d13dSmrg }
2454052d13dSmrg
2464052d13dSmrg sendcom(pp, REFRESH);
2474052d13dSmrg sendcom(pp, READY, 0);
2484052d13dSmrg (void) fflush(pp->p_output);
2494052d13dSmrg }
2504052d13dSmrg #endif
2514052d13dSmrg
25275b3905dSdholland static void
stplayer(PLAYER * newpp,int enter_status)253fbca3d8cSdholland stplayer(PLAYER *newpp, int enter_status)
2544052d13dSmrg {
255544a5e33Slukem int x, y;
256544a5e33Slukem PLAYER *pp;
2574052d13dSmrg
2584052d13dSmrg Nplayer++;
2594052d13dSmrg
2604052d13dSmrg for (y = 0; y < UBOUND; y++)
2614052d13dSmrg for (x = 0; x < WIDTH; x++)
2624052d13dSmrg newpp->p_maze[y][x] = Maze[y][x];
2634052d13dSmrg for ( ; y < DBOUND; y++) {
2644052d13dSmrg for (x = 0; x < LBOUND; x++)
2654052d13dSmrg newpp->p_maze[y][x] = Maze[y][x];
2664052d13dSmrg for ( ; x < RBOUND; x++)
2674052d13dSmrg newpp->p_maze[y][x] = SPACE;
2684052d13dSmrg for ( ; x < WIDTH; x++)
2694052d13dSmrg newpp->p_maze[y][x] = Maze[y][x];
2704052d13dSmrg }
2714052d13dSmrg for ( ; y < HEIGHT; y++)
2724052d13dSmrg for (x = 0; x < WIDTH; x++)
2734052d13dSmrg newpp->p_maze[y][x] = Maze[y][x];
2744052d13dSmrg
2754052d13dSmrg do {
2764052d13dSmrg x = rand_num(WIDTH - 1) + 1;
2774052d13dSmrg y = rand_num(HEIGHT - 1) + 1;
2784052d13dSmrg } while (Maze[y][x] != SPACE);
2794052d13dSmrg newpp->p_over = SPACE;
2804052d13dSmrg newpp->p_x = x;
2814052d13dSmrg newpp->p_y = y;
28237a43147Sdholland newpp->p_undershot = false;
2834052d13dSmrg
2844052d13dSmrg #ifdef FLY
2854052d13dSmrg if (enter_status == Q_FLY) {
2864052d13dSmrg newpp->p_flying = rand_num(20);
2874052d13dSmrg newpp->p_flyx = 2 * rand_num(6) - 5;
2884052d13dSmrg newpp->p_flyy = 2 * rand_num(6) - 5;
2894052d13dSmrg newpp->p_face = FLYER;
2904052d13dSmrg }
2914052d13dSmrg else
2924052d13dSmrg #endif
2934052d13dSmrg {
2944052d13dSmrg newpp->p_flying = -1;
2954052d13dSmrg newpp->p_face = rand_dir();
2964052d13dSmrg }
2974052d13dSmrg newpp->p_damage = 0;
2984052d13dSmrg newpp->p_damcap = MAXDAM;
2994052d13dSmrg newpp->p_nchar = 0;
3004052d13dSmrg newpp->p_ncount = 0;
3014052d13dSmrg newpp->p_nexec = 0;
3024052d13dSmrg newpp->p_ammo = ISHOTS;
3034052d13dSmrg #ifdef BOOTS
3044052d13dSmrg newpp->p_nboots = 0;
3054052d13dSmrg #endif
3064052d13dSmrg if (enter_status == Q_SCAN) {
3074052d13dSmrg newpp->p_scan = SCANLEN;
3084052d13dSmrg newpp->p_cloak = 0;
3094052d13dSmrg }
3104052d13dSmrg else {
3114052d13dSmrg newpp->p_scan = 0;
3124052d13dSmrg newpp->p_cloak = CLOAKLEN;
3134052d13dSmrg }
3144052d13dSmrg newpp->p_ncshot = 0;
3154052d13dSmrg
3164052d13dSmrg do {
3174052d13dSmrg x = rand_num(WIDTH - 1) + 1;
3184052d13dSmrg y = rand_num(HEIGHT - 1) + 1;
3194052d13dSmrg } while (Maze[y][x] != SPACE);
3204052d13dSmrg Maze[y][x] = GMINE;
3214052d13dSmrg #ifdef MONITOR
3224052d13dSmrg for (pp = Monitor; pp < End_monitor; pp++)
3234052d13dSmrg check(pp, y, x);
3244052d13dSmrg #endif
3254052d13dSmrg
3264052d13dSmrg do {
3274052d13dSmrg x = rand_num(WIDTH - 1) + 1;
3284052d13dSmrg y = rand_num(HEIGHT - 1) + 1;
3294052d13dSmrg } while (Maze[y][x] != SPACE);
3304052d13dSmrg Maze[y][x] = MINE;
3314052d13dSmrg #ifdef MONITOR
3324052d13dSmrg for (pp = Monitor; pp < End_monitor; pp++)
3334052d13dSmrg check(pp, y, x);
3344052d13dSmrg #endif
3354052d13dSmrg
3360ed1b742Sdholland (void) snprintf(Buf, sizeof(Buf), "%5.2f%c%-10.10s %c",
3370ed1b742Sdholland newpp->p_ident->i_score,
3384052d13dSmrg stat_char(newpp), newpp->p_ident->i_name,
3394052d13dSmrg newpp->p_ident->i_team);
3404052d13dSmrg y = STAT_PLAY_ROW + 1 + (newpp - Player);
3414052d13dSmrg for (pp = Player; pp < End_player; pp++) {
3424052d13dSmrg if (pp != newpp) {
3434c08f5f9Sdholland char smallbuf[16];
3444052d13dSmrg
3454052d13dSmrg pp->p_ammo += NSHOTS;
3464052d13dSmrg newpp->p_ammo += NSHOTS;
3474052d13dSmrg cgoto(pp, y, STAT_NAME_COL);
3484052d13dSmrg outstr(pp, Buf, STAT_NAME_LEN);
3490ed1b742Sdholland (void) snprintf(smallbuf, sizeof(smallbuf),
3500ed1b742Sdholland "%3d", pp->p_ammo);
3514052d13dSmrg cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
3524052d13dSmrg outstr(pp, smallbuf, 3);
3534052d13dSmrg }
3544052d13dSmrg }
3554052d13dSmrg #ifdef MONITOR
3564052d13dSmrg for (pp = Monitor; pp < End_monitor; pp++) {
3574052d13dSmrg cgoto(pp, y, STAT_NAME_COL);
3584052d13dSmrg outstr(pp, Buf, STAT_NAME_LEN);
3594052d13dSmrg }
3604052d13dSmrg #endif
3614052d13dSmrg
3624052d13dSmrg drawmaze(newpp);
36337a43147Sdholland drawplayer(newpp, true);
3644052d13dSmrg look(newpp);
3654052d13dSmrg #ifdef FLY
3664052d13dSmrg if (enter_status == Q_FLY)
3674052d13dSmrg /* Make sure that the position you enter in will be erased */
3684052d13dSmrg showexpl(newpp->p_y, newpp->p_x, FLYER);
3694052d13dSmrg #endif
3704052d13dSmrg sendcom(newpp, REFRESH);
3714052d13dSmrg sendcom(newpp, READY, 0);
3724052d13dSmrg (void) fflush(newpp->p_output);
3734052d13dSmrg }
3744052d13dSmrg
3754052d13dSmrg /*
3764052d13dSmrg * rand_dir:
3774052d13dSmrg * Return a random direction
3784052d13dSmrg */
379544a5e33Slukem int
rand_dir(void)380fbca3d8cSdholland rand_dir(void)
3814052d13dSmrg {
3824052d13dSmrg switch (rand_num(4)) {
3834052d13dSmrg case 0:
3844052d13dSmrg return LEFTS;
3854052d13dSmrg case 1:
3864052d13dSmrg return RIGHT;
3874052d13dSmrg case 2:
3884052d13dSmrg return BELOW;
3894052d13dSmrg case 3:
3904052d13dSmrg return ABOVE;
3914052d13dSmrg }
3924052d13dSmrg /* NOTREACHED */
393544a5e33Slukem return(-1);
3944052d13dSmrg }
3954052d13dSmrg
3964052d13dSmrg /*
3974052d13dSmrg * get_ident:
3984052d13dSmrg * Get the score structure of a player
3994052d13dSmrg */
40075b3905dSdholland static IDENT *
get_ident(uint32_t machine,uint32_t uid,const char * name,char team)401c560d1b1Sdholland get_ident(uint32_t machine, uint32_t uid, const char *name, char team)
4024052d13dSmrg {
403544a5e33Slukem IDENT *ip;
4044052d13dSmrg static IDENT punt;
4054052d13dSmrg
4064052d13dSmrg for (ip = Scores; ip != NULL; ip = ip->i_next)
4074052d13dSmrg if (ip->i_machine == machine
4084052d13dSmrg && ip->i_uid == uid
4094052d13dSmrg && ip->i_team == team
410c560d1b1Sdholland && strncmp(ip->i_name, name, WIRE_NAMELEN) == 0)
4114052d13dSmrg break;
4124052d13dSmrg
4134052d13dSmrg if (ip != NULL) {
4144052d13dSmrg if (ip->i_entries < SCOREDECAY)
4154052d13dSmrg ip->i_entries++;
4164052d13dSmrg else
4174052d13dSmrg ip->i_kills = (ip->i_kills * (SCOREDECAY - 1))
4184052d13dSmrg / SCOREDECAY;
4194052d13dSmrg ip->i_score = ip->i_kills / (double) ip->i_entries;
4204052d13dSmrg }
4214052d13dSmrg else {
4226ffae662Sdholland ip = malloc(sizeof(*ip));
4234052d13dSmrg if (ip == NULL) {
4244052d13dSmrg /* Fourth down, time to punt */
4254052d13dSmrg ip = &punt;
4264052d13dSmrg }
4274052d13dSmrg ip->i_machine = machine;
4284052d13dSmrg ip->i_team = team;
4294052d13dSmrg ip->i_uid = uid;
430c560d1b1Sdholland strncpy(ip->i_name, name, sizeof(ip->i_name));
4314052d13dSmrg ip->i_kills = 0;
4324052d13dSmrg ip->i_entries = 1;
4334052d13dSmrg ip->i_score = 0;
4344052d13dSmrg ip->i_absorbed = 0;
4354052d13dSmrg ip->i_faced = 0;
4364052d13dSmrg ip->i_shot = 0;
4374052d13dSmrg ip->i_robbed = 0;
4384052d13dSmrg ip->i_slime = 0;
4394052d13dSmrg ip->i_missed = 0;
4404052d13dSmrg ip->i_ducked = 0;
4414052d13dSmrg ip->i_gkills = ip->i_bkills = ip->i_deaths = 0;
4424052d13dSmrg ip->i_stillb = ip->i_saved = 0;
4434052d13dSmrg ip->i_next = Scores;
4444052d13dSmrg Scores = ip;
4454052d13dSmrg }
4464052d13dSmrg
4474052d13dSmrg return ip;
4484052d13dSmrg }
449