1 /* $NetBSD: answer.c,v 1.15 2009/08/12 07:42:11 dholland Exp $ */
3 * Copyright (c) 1983-2003, Regents of the University of California.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
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
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.
33 #include <sys/cdefs.h>
35 __RCSID("$NetBSD: answer.c,v 1.15 2009/08/12 07:42:11 dholland Exp $");
47 static char Ttyname
[NAMELEN
];
49 static IDENT
*get_ident(uint32_t, uint32_t, char *, char);
50 static void stmonitor(PLAYER
*);
51 static void stplayer(PLAYER
*, int);
59 static char name
[NAMELEN
];
61 static int enter_status
;
62 static socklen_t socklen
;
63 static uint32_t machine
;
65 static SOCKET sockstruct
;
72 socklen
= sizeof sockstruct
;
74 socklen
= sizeof sockstruct
- 1;
77 newsock
= accept(Socket
, (struct sockaddr
*) &sockstruct
, &socklen
);
83 syslog(LOG_ERR
, "accept: %m");
91 machine
= ntohl(((struct sockaddr_in
*) &sockstruct
)->sin_addr
.s_addr
);
94 machine
= gethostid();
96 version
= htonl((uint32_t) HUNT_VERSION
);
97 (void) write(newsock
, &version
, LONGLEN
);
98 (void) read(newsock
, &uid
, LONGLEN
);
100 (void) read(newsock
, name
, NAMELEN
);
101 (void) read(newsock
, &team
, 1);
102 (void) read(newsock
, &enter_status
, LONGLEN
);
103 enter_status
= ntohl((unsigned long) enter_status
);
104 (void) read(newsock
, Ttyname
, NAMELEN
);
105 (void) read(newsock
, &mode
, sizeof mode
);
109 * Ensure null termination.
111 name
[sizeof(name
)-1] = '\0';
112 Ttyname
[sizeof(Ttyname
)-1] = '\0';
115 * Turn off blocking I/O, so a slow or dead terminal won't stop
116 * the game. All subsequent reads check how many bytes they read.
118 flags
= fcntl(newsock
, F_GETFL
, 0);
120 (void) fcntl(newsock
, F_SETFL
, flags
);
123 * Make sure the name contains only printable characters
124 * since we use control characters for cursor control
125 * between driver and player processes
127 for (cp1
= cp2
= name
; *cp1
!= '\0'; cp1
++)
128 if (isprint((unsigned char)*cp1
) || *cp1
== ' ')
133 if (mode
== C_MESSAGE
) {
134 char buf
[BUFSIZ
+ 1];
138 (void) snprintf(buf
, sizeof(buf
), "%s: ", name
);
140 (void) snprintf(buf
, sizeof(buf
), "%s[%c]: ", name
,
143 for (pp
= Player
; pp
< End_player
; pp
++) {
144 cgoto(pp
, HEIGHT
, 0);
147 while ((n
= read(newsock
, buf
, BUFSIZ
)) > 0)
148 for (pp
= Player
; pp
< End_player
; pp
++)
150 for (pp
= Player
; pp
< End_player
; pp
++) {
152 sendcom(pp
, REFRESH
);
153 sendcom(pp
, READY
, 0);
154 (void) fflush(pp
->p_output
);
156 (void) close(newsock
);
162 if (mode
== C_MONITOR
)
163 if (End_monitor
< &Monitor
[MAXMON
]) {
165 i
= pp
- Monitor
+ MAXPL
+ 3;
168 (void) write(newsock
, &socklen
,
170 (void) close(newsock
);
175 if (End_player
< &Player
[MAXPL
]) {
180 (void) write(newsock
, &socklen
,
182 (void) close(newsock
);
187 if (mode
== C_MONITOR
&& team
== ' ')
190 pp
->p_ident
= get_ident(machine
, uid
, name
, team
);
191 pp
->p_output
= fdopen(newsock
, "w");
192 pp
->p_death
[0] = '\0';
194 fdset
[i
].fd
= newsock
;
195 fdset
[i
].events
= POLLIN
;
201 if (mode
== C_MONITOR
)
205 stplayer(pp
, enter_status
);
211 stmonitor(PLAYER
*pp
)
216 memcpy(pp
->p_maze
, Maze
, sizeof Maze
);
220 (void) snprintf(Buf
, sizeof(Buf
), "%5.5s%c%-10.10s %c", " ",
222 pp
->p_ident
->i_name
, pp
->p_ident
->i_team
);
223 line
= STAT_MON_ROW
+ 1 + (pp
- Monitor
);
224 for (npp
= Player
; npp
< End_player
; npp
++) {
225 cgoto(npp
, line
, STAT_NAME_COL
);
226 outstr(npp
, Buf
, STAT_NAME_LEN
);
228 for (npp
= Monitor
; npp
< End_monitor
; npp
++) {
229 cgoto(npp
, line
, STAT_NAME_COL
);
230 outstr(npp
, Buf
, STAT_NAME_LEN
);
233 sendcom(pp
, REFRESH
);
234 sendcom(pp
, READY
, 0);
235 (void) fflush(pp
->p_output
);
240 stplayer(PLAYER
*newpp
, int enter_status
)
247 for (y
= 0; y
< UBOUND
; y
++)
248 for (x
= 0; x
< WIDTH
; x
++)
249 newpp
->p_maze
[y
][x
] = Maze
[y
][x
];
250 for ( ; y
< DBOUND
; y
++) {
251 for (x
= 0; x
< LBOUND
; x
++)
252 newpp
->p_maze
[y
][x
] = Maze
[y
][x
];
253 for ( ; x
< RBOUND
; x
++)
254 newpp
->p_maze
[y
][x
] = SPACE
;
255 for ( ; x
< WIDTH
; x
++)
256 newpp
->p_maze
[y
][x
] = Maze
[y
][x
];
258 for ( ; y
< HEIGHT
; y
++)
259 for (x
= 0; x
< WIDTH
; x
++)
260 newpp
->p_maze
[y
][x
] = Maze
[y
][x
];
263 x
= rand_num(WIDTH
- 1) + 1;
264 y
= rand_num(HEIGHT
- 1) + 1;
265 } while (Maze
[y
][x
] != SPACE
);
266 newpp
->p_over
= SPACE
;
269 newpp
->p_undershot
= FALSE
;
272 if (enter_status
== Q_FLY
) {
273 newpp
->p_flying
= rand_num(20);
274 newpp
->p_flyx
= 2 * rand_num(6) - 5;
275 newpp
->p_flyy
= 2 * rand_num(6) - 5;
276 newpp
->p_face
= FLYER
;
281 newpp
->p_flying
= -1;
282 newpp
->p_face
= rand_dir();
285 newpp
->p_damcap
= MAXDAM
;
289 newpp
->p_ammo
= ISHOTS
;
293 if (enter_status
== Q_SCAN
) {
294 newpp
->p_scan
= SCANLEN
;
299 newpp
->p_cloak
= CLOAKLEN
;
304 x
= rand_num(WIDTH
- 1) + 1;
305 y
= rand_num(HEIGHT
- 1) + 1;
306 } while (Maze
[y
][x
] != SPACE
);
309 for (pp
= Monitor
; pp
< End_monitor
; pp
++)
314 x
= rand_num(WIDTH
- 1) + 1;
315 y
= rand_num(HEIGHT
- 1) + 1;
316 } while (Maze
[y
][x
] != SPACE
);
319 for (pp
= Monitor
; pp
< End_monitor
; pp
++)
323 (void) snprintf(Buf
, sizeof(Buf
), "%5.2f%c%-10.10s %c",
324 newpp
->p_ident
->i_score
,
325 stat_char(newpp
), newpp
->p_ident
->i_name
,
326 newpp
->p_ident
->i_team
);
327 y
= STAT_PLAY_ROW
+ 1 + (newpp
- Player
);
328 for (pp
= Player
; pp
< End_player
; pp
++) {
332 pp
->p_ammo
+= NSHOTS
;
333 newpp
->p_ammo
+= NSHOTS
;
334 cgoto(pp
, y
, STAT_NAME_COL
);
335 outstr(pp
, Buf
, STAT_NAME_LEN
);
336 (void) snprintf(smallbuf
, sizeof(smallbuf
),
338 cgoto(pp
, STAT_AMMO_ROW
, STAT_VALUE_COL
);
339 outstr(pp
, smallbuf
, 3);
343 for (pp
= Monitor
; pp
< End_monitor
; pp
++) {
344 cgoto(pp
, y
, STAT_NAME_COL
);
345 outstr(pp
, Buf
, STAT_NAME_LEN
);
350 drawplayer(newpp
, TRUE
);
353 if (enter_status
== Q_FLY
)
354 /* Make sure that the position you enter in will be erased */
355 showexpl(newpp
->p_y
, newpp
->p_x
, FLYER
);
357 sendcom(newpp
, REFRESH
);
358 sendcom(newpp
, READY
, 0);
359 (void) fflush(newpp
->p_output
);
364 * Return a random direction
369 switch (rand_num(4)) {
385 * Get the score structure of a player
388 get_ident(uint32_t machine
, uint32_t uid
, char *name
, char team
)
393 for (ip
= Scores
; ip
!= NULL
; ip
= ip
->i_next
)
394 if (ip
->i_machine
== machine
396 && ip
->i_team
== team
397 && strncmp(ip
->i_name
, name
, NAMELEN
) == 0)
401 if (ip
->i_entries
< SCOREDECAY
)
404 ip
->i_kills
= (ip
->i_kills
* (SCOREDECAY
- 1))
406 ip
->i_score
= ip
->i_kills
/ (double) ip
->i_entries
;
409 ip
= malloc(sizeof(*ip
));
411 /* Fourth down, time to punt */
414 ip
->i_machine
= machine
;
417 strncpy(ip
->i_name
, name
, NAMELEN
);
428 ip
->i_gkills
= ip
->i_bkills
= ip
->i_deaths
= 0;
429 ip
->i_stillb
= ip
->i_saved
= 0;