]>
git.cameronkatri.com Git - bsdgames-darwin.git/blob - hunt/huntd/answer.c
1 /* $NetBSD: answer.c,v 1.24 2021/05/02 12:50:45 rillig 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.24 2021/05/02 12:50:45 rillig Exp $");
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <netinet/in.h>
51 static char Ttyname
[WIRE_NAMELEN
];
53 static IDENT
*get_ident(uint32_t, uint32_t, const char *, char);
54 static void stmonitor(PLAYER
*);
55 static void stplayer(PLAYER
*, int);
63 static char name
[WIRE_NAMELEN
];
65 static int32_t enter_status
;
66 static socklen_t socklen
;
67 static uint32_t machine
;
69 static struct sockaddr_storage newaddr
;
75 socklen
= sizeof(newaddr
);
76 newsock
= accept(huntsock
, (struct sockaddr
*)&newaddr
, &socklen
);
80 complain(LOG_ERR
, "accept");
85 * XXX this is pretty bollocks
87 switch (newaddr
.ss_family
) {
89 machine
= ((struct sockaddr_in
*)&newaddr
)->sin_addr
.s_addr
;
90 machine
= ntohl(machine
);
94 struct sockaddr_in6
*sin6
;
96 sin6
= (struct sockaddr_in6
*)&newaddr
;
97 assert(sizeof(sin6
->sin6_addr
.s6_addr
) >
99 memcpy(&machine
, sin6
->sin6_addr
.s6_addr
,
104 machine
= gethostid();
111 version
= htonl((uint32_t) HUNT_VERSION
);
112 (void) write(newsock
, &version
, sizeof(version
));
113 (void) read(newsock
, &uid
, sizeof(uid
));
115 (void) read(newsock
, name
, sizeof(name
));
116 (void) read(newsock
, &team
, 1);
117 (void) read(newsock
, &enter_status
, sizeof(enter_status
));
118 enter_status
= ntohl(enter_status
);
119 (void) read(newsock
, Ttyname
, sizeof(Ttyname
));
120 (void) read(newsock
, &mode
, sizeof(mode
));
124 * Ensure null termination.
126 name
[sizeof(name
)-1] = '\0';
127 Ttyname
[sizeof(Ttyname
)-1] = '\0';
130 * Turn off blocking I/O, so a slow or dead terminal won't stop
131 * the game. All subsequent reads check how many bytes they read.
133 flags
= fcntl(newsock
, F_GETFL
, 0);
135 (void) fcntl(newsock
, F_SETFL
, flags
);
138 * Make sure the name contains only printable characters
139 * since we use control characters for cursor control
140 * between driver and player processes
142 for (cp1
= cp2
= name
; *cp1
!= '\0'; cp1
++)
143 if (isprint((unsigned char)*cp1
) || *cp1
== ' ')
147 if (mode
== C_MESSAGE
) {
148 char buf
[BUFSIZ
+ 1];
152 (void) snprintf(buf
, sizeof(buf
), "%s: ", name
);
154 (void) snprintf(buf
, sizeof(buf
), "%s[%c]: ", name
,
157 for (pp
= Player
; pp
< End_player
; pp
++) {
158 cgoto(pp
, HEIGHT
, 0);
161 while ((n
= read(newsock
, buf
, BUFSIZ
)) > 0)
162 for (pp
= Player
; pp
< End_player
; pp
++)
164 for (pp
= Player
; pp
< End_player
; pp
++) {
166 sendcom(pp
, REFRESH
);
167 sendcom(pp
, READY
, 0);
168 (void) fflush(pp
->p_output
);
170 (void) close(newsock
);
175 if (mode
== C_MONITOR
)
176 if (End_monitor
< &Monitor
[MAXMON
]) {
178 i
= pp
- Monitor
+ MAXPL
+ 3;
181 (void) write(newsock
, &socklen
,
183 (void) close(newsock
);
188 if (End_player
< &Player
[MAXPL
]) {
193 (void) write(newsock
, &socklen
,
195 (void) close(newsock
);
200 if (mode
== C_MONITOR
&& team
== ' ')
203 pp
->p_ident
= get_ident(machine
, uid
, name
, team
);
204 pp
->p_output
= fdopen(newsock
, "w");
205 pp
->p_death
[0] = '\0';
207 fdset
[i
].fd
= newsock
;
208 fdset
[i
].events
= POLLIN
;
214 if (mode
== C_MONITOR
)
218 stplayer(pp
, enter_status
);
224 stmonitor(PLAYER
*pp
)
229 memcpy(pp
->p_maze
, Maze
, sizeof Maze
);
233 (void) snprintf(Buf
, sizeof(Buf
), "%5.5s%c%-10.10s %c", " ",
235 pp
->p_ident
->i_name
, pp
->p_ident
->i_team
);
236 line
= STAT_MON_ROW
+ 1 + (pp
- Monitor
);
237 for (npp
= Player
; npp
< End_player
; npp
++) {
238 cgoto(npp
, line
, STAT_NAME_COL
);
239 outstr(npp
, Buf
, STAT_NAME_LEN
);
241 for (npp
= Monitor
; npp
< End_monitor
; npp
++) {
242 cgoto(npp
, line
, STAT_NAME_COL
);
243 outstr(npp
, Buf
, STAT_NAME_LEN
);
246 sendcom(pp
, REFRESH
);
247 sendcom(pp
, READY
, 0);
248 (void) fflush(pp
->p_output
);
253 stplayer(PLAYER
*newpp
, int enter_status
)
260 for (y
= 0; y
< UBOUND
; y
++)
261 for (x
= 0; x
< WIDTH
; x
++)
262 newpp
->p_maze
[y
][x
] = Maze
[y
][x
];
263 for ( ; y
< DBOUND
; y
++) {
264 for (x
= 0; x
< LBOUND
; x
++)
265 newpp
->p_maze
[y
][x
] = Maze
[y
][x
];
266 for ( ; x
< RBOUND
; x
++)
267 newpp
->p_maze
[y
][x
] = SPACE
;
268 for ( ; x
< WIDTH
; x
++)
269 newpp
->p_maze
[y
][x
] = Maze
[y
][x
];
271 for ( ; y
< HEIGHT
; y
++)
272 for (x
= 0; x
< WIDTH
; x
++)
273 newpp
->p_maze
[y
][x
] = Maze
[y
][x
];
276 x
= rand_num(WIDTH
- 1) + 1;
277 y
= rand_num(HEIGHT
- 1) + 1;
278 } while (Maze
[y
][x
] != SPACE
);
279 newpp
->p_over
= SPACE
;
282 newpp
->p_undershot
= false;
285 if (enter_status
== Q_FLY
) {
286 newpp
->p_flying
= rand_num(20);
287 newpp
->p_flyx
= 2 * rand_num(6) - 5;
288 newpp
->p_flyy
= 2 * rand_num(6) - 5;
289 newpp
->p_face
= FLYER
;
294 newpp
->p_flying
= -1;
295 newpp
->p_face
= rand_dir();
298 newpp
->p_damcap
= MAXDAM
;
302 newpp
->p_ammo
= ISHOTS
;
306 if (enter_status
== Q_SCAN
) {
307 newpp
->p_scan
= SCANLEN
;
312 newpp
->p_cloak
= CLOAKLEN
;
317 x
= rand_num(WIDTH
- 1) + 1;
318 y
= rand_num(HEIGHT
- 1) + 1;
319 } while (Maze
[y
][x
] != SPACE
);
322 for (pp
= Monitor
; pp
< End_monitor
; pp
++)
327 x
= rand_num(WIDTH
- 1) + 1;
328 y
= rand_num(HEIGHT
- 1) + 1;
329 } while (Maze
[y
][x
] != SPACE
);
332 for (pp
= Monitor
; pp
< End_monitor
; pp
++)
336 (void) snprintf(Buf
, sizeof(Buf
), "%5.2f%c%-10.10s %c",
337 newpp
->p_ident
->i_score
,
338 stat_char(newpp
), newpp
->p_ident
->i_name
,
339 newpp
->p_ident
->i_team
);
340 y
= STAT_PLAY_ROW
+ 1 + (newpp
- Player
);
341 for (pp
= Player
; pp
< End_player
; pp
++) {
345 pp
->p_ammo
+= NSHOTS
;
346 newpp
->p_ammo
+= NSHOTS
;
347 cgoto(pp
, y
, STAT_NAME_COL
);
348 outstr(pp
, Buf
, STAT_NAME_LEN
);
349 (void) snprintf(smallbuf
, sizeof(smallbuf
),
351 cgoto(pp
, STAT_AMMO_ROW
, STAT_VALUE_COL
);
352 outstr(pp
, smallbuf
, 3);
356 for (pp
= Monitor
; pp
< End_monitor
; pp
++) {
357 cgoto(pp
, y
, STAT_NAME_COL
);
358 outstr(pp
, Buf
, STAT_NAME_LEN
);
363 drawplayer(newpp
, true);
366 if (enter_status
== Q_FLY
)
367 /* Make sure that the position you enter in will be erased */
368 showexpl(newpp
->p_y
, newpp
->p_x
, FLYER
);
370 sendcom(newpp
, REFRESH
);
371 sendcom(newpp
, READY
, 0);
372 (void) fflush(newpp
->p_output
);
377 * Return a random direction
382 switch (rand_num(4)) {
398 * Get the score structure of a player
401 get_ident(uint32_t machine
, uint32_t uid
, const char *name
, char team
)
406 for (ip
= Scores
; ip
!= NULL
; ip
= ip
->i_next
)
407 if (ip
->i_machine
== machine
409 && ip
->i_team
== team
410 && strncmp(ip
->i_name
, name
, WIRE_NAMELEN
) == 0)
414 if (ip
->i_entries
< SCOREDECAY
)
417 ip
->i_kills
= (ip
->i_kills
* (SCOREDECAY
- 1))
419 ip
->i_score
= ip
->i_kills
/ (double) ip
->i_entries
;
422 ip
= malloc(sizeof(*ip
));
424 /* Fourth down, time to punt */
427 ip
->i_machine
= machine
;
430 strncpy(ip
->i_name
, name
, sizeof(ip
->i_name
));
441 ip
->i_gkills
= ip
->i_bkills
= ip
->i_deaths
= 0;
442 ip
->i_stillb
= ip
->i_saved
= 0;