]>
git.cameronkatri.com Git - bsdgames-darwin.git/blob - hunt/huntd/answer.c
1 /* $NetBSD: answer.c,v 1.14 2009/07/04 04:29:54 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.14 2009/07/04 04:29:54 dholland Exp $");
47 static char Ttyname
[NAMELEN
];
55 static char name
[NAMELEN
];
57 static int enter_status
;
58 static socklen_t socklen
;
59 static uint32_t machine
;
61 static SOCKET sockstruct
;
68 socklen
= sizeof sockstruct
;
70 socklen
= sizeof sockstruct
- 1;
73 newsock
= accept(Socket
, (struct sockaddr
*) &sockstruct
, &socklen
);
79 syslog(LOG_ERR
, "accept: %m");
87 machine
= ntohl(((struct sockaddr_in
*) &sockstruct
)->sin_addr
.s_addr
);
90 machine
= gethostid();
92 version
= htonl((u_int32_t
) HUNT_VERSION
);
93 (void) write(newsock
, &version
, LONGLEN
);
94 (void) read(newsock
, &uid
, LONGLEN
);
96 (void) read(newsock
, name
, NAMELEN
);
97 (void) read(newsock
, &team
, 1);
98 (void) read(newsock
, &enter_status
, LONGLEN
);
99 enter_status
= ntohl((unsigned long) enter_status
);
100 (void) read(newsock
, Ttyname
, NAMELEN
);
101 (void) read(newsock
, &mode
, sizeof mode
);
105 * Ensure null termination.
107 name
[sizeof(name
)-1] = '\0';
108 Ttyname
[sizeof(Ttyname
)-1] = '\0';
111 * Turn off blocking I/O, so a slow or dead terminal won't stop
112 * the game. All subsequent reads check how many bytes they read.
114 flags
= fcntl(newsock
, F_GETFL
, 0);
116 (void) fcntl(newsock
, F_SETFL
, flags
);
119 * Make sure the name contains only printable characters
120 * since we use control characters for cursor control
121 * between driver and player processes
123 for (cp1
= cp2
= name
; *cp1
!= '\0'; cp1
++)
124 if (isprint((unsigned char)*cp1
) || *cp1
== ' ')
129 if (mode
== C_MESSAGE
) {
130 char buf
[BUFSIZ
+ 1];
134 (void) snprintf(buf
, sizeof(buf
), "%s: ", name
);
136 (void) snprintf(buf
, sizeof(buf
), "%s[%c]: ", name
,
139 for (pp
= Player
; pp
< End_player
; pp
++) {
140 cgoto(pp
, HEIGHT
, 0);
143 while ((n
= read(newsock
, buf
, BUFSIZ
)) > 0)
144 for (pp
= Player
; pp
< End_player
; pp
++)
146 for (pp
= Player
; pp
< End_player
; pp
++) {
148 sendcom(pp
, REFRESH
);
149 sendcom(pp
, READY
, 0);
150 (void) fflush(pp
->p_output
);
152 (void) close(newsock
);
158 if (mode
== C_MONITOR
)
159 if (End_monitor
< &Monitor
[MAXMON
]) {
161 i
= pp
- Monitor
+ MAXPL
+ 3;
164 (void) write(newsock
, &socklen
,
166 (void) close(newsock
);
171 if (End_player
< &Player
[MAXPL
]) {
176 (void) write(newsock
, &socklen
,
178 (void) close(newsock
);
183 if (mode
== C_MONITOR
&& team
== ' ')
186 pp
->p_ident
= get_ident(machine
, uid
, name
, team
);
187 pp
->p_output
= fdopen(newsock
, "w");
188 pp
->p_death
[0] = '\0';
190 fdset
[i
].fd
= newsock
;
191 fdset
[i
].events
= POLLIN
;
197 if (mode
== C_MONITOR
)
201 stplayer(pp
, enter_status
);
207 stmonitor(PLAYER
*pp
)
212 memcpy(pp
->p_maze
, Maze
, sizeof Maze
);
216 (void) snprintf(Buf
, sizeof(Buf
), "%5.5s%c%-10.10s %c", " ",
218 pp
->p_ident
->i_name
, pp
->p_ident
->i_team
);
219 line
= STAT_MON_ROW
+ 1 + (pp
- Monitor
);
220 for (npp
= Player
; npp
< End_player
; npp
++) {
221 cgoto(npp
, line
, STAT_NAME_COL
);
222 outstr(npp
, Buf
, STAT_NAME_LEN
);
224 for (npp
= Monitor
; npp
< End_monitor
; npp
++) {
225 cgoto(npp
, line
, STAT_NAME_COL
);
226 outstr(npp
, Buf
, STAT_NAME_LEN
);
229 sendcom(pp
, REFRESH
);
230 sendcom(pp
, READY
, 0);
231 (void) fflush(pp
->p_output
);
236 stplayer(PLAYER
*newpp
, int enter_status
)
243 for (y
= 0; y
< UBOUND
; y
++)
244 for (x
= 0; x
< WIDTH
; x
++)
245 newpp
->p_maze
[y
][x
] = Maze
[y
][x
];
246 for ( ; y
< DBOUND
; y
++) {
247 for (x
= 0; x
< LBOUND
; x
++)
248 newpp
->p_maze
[y
][x
] = Maze
[y
][x
];
249 for ( ; x
< RBOUND
; x
++)
250 newpp
->p_maze
[y
][x
] = SPACE
;
251 for ( ; x
< WIDTH
; x
++)
252 newpp
->p_maze
[y
][x
] = Maze
[y
][x
];
254 for ( ; y
< HEIGHT
; y
++)
255 for (x
= 0; x
< WIDTH
; x
++)
256 newpp
->p_maze
[y
][x
] = Maze
[y
][x
];
259 x
= rand_num(WIDTH
- 1) + 1;
260 y
= rand_num(HEIGHT
- 1) + 1;
261 } while (Maze
[y
][x
] != SPACE
);
262 newpp
->p_over
= SPACE
;
265 newpp
->p_undershot
= FALSE
;
268 if (enter_status
== Q_FLY
) {
269 newpp
->p_flying
= rand_num(20);
270 newpp
->p_flyx
= 2 * rand_num(6) - 5;
271 newpp
->p_flyy
= 2 * rand_num(6) - 5;
272 newpp
->p_face
= FLYER
;
277 newpp
->p_flying
= -1;
278 newpp
->p_face
= rand_dir();
281 newpp
->p_damcap
= MAXDAM
;
285 newpp
->p_ammo
= ISHOTS
;
289 if (enter_status
== Q_SCAN
) {
290 newpp
->p_scan
= SCANLEN
;
295 newpp
->p_cloak
= CLOAKLEN
;
300 x
= rand_num(WIDTH
- 1) + 1;
301 y
= rand_num(HEIGHT
- 1) + 1;
302 } while (Maze
[y
][x
] != SPACE
);
305 for (pp
= Monitor
; pp
< End_monitor
; pp
++)
310 x
= rand_num(WIDTH
- 1) + 1;
311 y
= rand_num(HEIGHT
- 1) + 1;
312 } while (Maze
[y
][x
] != SPACE
);
315 for (pp
= Monitor
; pp
< End_monitor
; pp
++)
319 (void) snprintf(Buf
, sizeof(Buf
), "%5.2f%c%-10.10s %c",
320 newpp
->p_ident
->i_score
,
321 stat_char(newpp
), newpp
->p_ident
->i_name
,
322 newpp
->p_ident
->i_team
);
323 y
= STAT_PLAY_ROW
+ 1 + (newpp
- Player
);
324 for (pp
= Player
; pp
< End_player
; pp
++) {
328 pp
->p_ammo
+= NSHOTS
;
329 newpp
->p_ammo
+= NSHOTS
;
330 cgoto(pp
, y
, STAT_NAME_COL
);
331 outstr(pp
, Buf
, STAT_NAME_LEN
);
332 (void) snprintf(smallbuf
, sizeof(smallbuf
),
334 cgoto(pp
, STAT_AMMO_ROW
, STAT_VALUE_COL
);
335 outstr(pp
, smallbuf
, 3);
339 for (pp
= Monitor
; pp
< End_monitor
; pp
++) {
340 cgoto(pp
, y
, STAT_NAME_COL
);
341 outstr(pp
, Buf
, STAT_NAME_LEN
);
346 drawplayer(newpp
, TRUE
);
349 if (enter_status
== Q_FLY
)
350 /* Make sure that the position you enter in will be erased */
351 showexpl(newpp
->p_y
, newpp
->p_x
, FLYER
);
353 sendcom(newpp
, REFRESH
);
354 sendcom(newpp
, READY
, 0);
355 (void) fflush(newpp
->p_output
);
360 * Return a random direction
365 switch (rand_num(4)) {
381 * Get the score structure of a player
384 get_ident(uint32_t machine
, uint32_t uid
, char *name
, char team
)
389 for (ip
= Scores
; ip
!= NULL
; ip
= ip
->i_next
)
390 if (ip
->i_machine
== machine
392 && ip
->i_team
== team
393 && strncmp(ip
->i_name
, name
, NAMELEN
) == 0)
397 if (ip
->i_entries
< SCOREDECAY
)
400 ip
->i_kills
= (ip
->i_kills
* (SCOREDECAY
- 1))
402 ip
->i_score
= ip
->i_kills
/ (double) ip
->i_entries
;
405 ip
= malloc(sizeof(*ip
));
407 /* Fourth down, time to punt */
410 ip
->i_machine
= machine
;
413 strncpy(ip
->i_name
, name
, NAMELEN
);
424 ip
->i_gkills
= ip
->i_bkills
= ip
->i_deaths
= 0;
425 ip
->i_stillb
= ip
->i_saved
= 0;