]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - hunt/huntd/answer.c
Whitespace.
[bsdgames-darwin.git] / hunt / huntd / answer.c
1 /* $NetBSD: answer.c,v 1.14 2009/07/04 04:29:54 dholland Exp $ */
2 /*
3 * Copyright (c) 1983-2003, Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
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
18 * permission.
19 *
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.
31 */
32
33 #include <sys/cdefs.h>
34 #ifndef lint
35 __RCSID("$NetBSD: answer.c,v 1.14 2009/07/04 04:29:54 dholland Exp $");
36 #endif /* not lint */
37
38 #include <ctype.h>
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43 #include "hunt.h"
44
45 #define SCOREDECAY 15
46
47 static char Ttyname[NAMELEN];
48
49 int
50 answer(void)
51 {
52 PLAYER *pp;
53 int newsock;
54 static u_long mode;
55 static char name[NAMELEN];
56 static char team;
57 static int enter_status;
58 static socklen_t socklen;
59 static uint32_t machine;
60 static uint32_t uid;
61 static SOCKET sockstruct;
62 char *cp1, *cp2;
63 int flags;
64 u_int32_t version;
65 int i;
66
67 #ifdef INTERNET
68 socklen = sizeof sockstruct;
69 #else
70 socklen = sizeof sockstruct - 1;
71 #endif
72 errno = 0;
73 newsock = accept(Socket, (struct sockaddr *) &sockstruct, &socklen);
74 if (newsock < 0)
75 {
76 if (errno == EINTR)
77 return FALSE;
78 #ifdef LOG
79 syslog(LOG_ERR, "accept: %m");
80 #else
81 perror("accept");
82 #endif
83 cleanup(1);
84 }
85
86 #ifdef INTERNET
87 machine = ntohl(((struct sockaddr_in *) &sockstruct)->sin_addr.s_addr);
88 #else
89 if (machine == 0)
90 machine = gethostid();
91 #endif
92 version = htonl((u_int32_t) HUNT_VERSION);
93 (void) write(newsock, &version, LONGLEN);
94 (void) read(newsock, &uid, LONGLEN);
95 uid = ntohl(uid);
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);
102 mode = ntohl(mode);
103
104 /*
105 * Ensure null termination.
106 */
107 name[sizeof(name)-1] = '\0';
108 Ttyname[sizeof(Ttyname)-1] = '\0';
109
110 /*
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.
113 */
114 flags = fcntl(newsock, F_GETFL, 0);
115 flags |= O_NDELAY;
116 (void) fcntl(newsock, F_SETFL, flags);
117
118 /*
119 * Make sure the name contains only printable characters
120 * since we use control characters for cursor control
121 * between driver and player processes
122 */
123 for (cp1 = cp2 = name; *cp1 != '\0'; cp1++)
124 if (isprint((unsigned char)*cp1) || *cp1 == ' ')
125 *cp2++ = *cp1;
126 *cp2 = '\0';
127
128 #ifdef INTERNET
129 if (mode == C_MESSAGE) {
130 char buf[BUFSIZ + 1];
131 int n;
132
133 if (team == ' ')
134 (void) snprintf(buf, sizeof(buf), "%s: ", name);
135 else
136 (void) snprintf(buf, sizeof(buf), "%s[%c]: ", name,
137 team);
138 n = strlen(buf);
139 for (pp = Player; pp < End_player; pp++) {
140 cgoto(pp, HEIGHT, 0);
141 outstr(pp, buf, n);
142 }
143 while ((n = read(newsock, buf, BUFSIZ)) > 0)
144 for (pp = Player; pp < End_player; pp++)
145 outstr(pp, buf, n);
146 for (pp = Player; pp < End_player; pp++) {
147 ce(pp);
148 sendcom(pp, REFRESH);
149 sendcom(pp, READY, 0);
150 (void) fflush(pp->p_output);
151 }
152 (void) close(newsock);
153 return FALSE;
154 }
155 else
156 #endif
157 #ifdef MONITOR
158 if (mode == C_MONITOR)
159 if (End_monitor < &Monitor[MAXMON]) {
160 pp = End_monitor++;
161 i = pp - Monitor + MAXPL + 3;
162 } else {
163 socklen = 0;
164 (void) write(newsock, &socklen,
165 sizeof socklen);
166 (void) close(newsock);
167 return FALSE;
168 }
169 else
170 #endif
171 if (End_player < &Player[MAXPL]) {
172 pp = End_player++;
173 i = pp - Player + 3;
174 } else {
175 socklen = 0;
176 (void) write(newsock, &socklen,
177 sizeof socklen);
178 (void) close(newsock);
179 return FALSE;
180 }
181
182 #ifdef MONITOR
183 if (mode == C_MONITOR && team == ' ')
184 team = '*';
185 #endif
186 pp->p_ident = get_ident(machine, uid, name, team);
187 pp->p_output = fdopen(newsock, "w");
188 pp->p_death[0] = '\0';
189 pp->p_fd = newsock;
190 fdset[i].fd = newsock;
191 fdset[i].events = POLLIN;
192
193 pp->p_y = 0;
194 pp->p_x = 0;
195
196 #ifdef MONITOR
197 if (mode == C_MONITOR)
198 stmonitor(pp);
199 else
200 #endif
201 stplayer(pp, enter_status);
202 return TRUE;
203 }
204
205 #ifdef MONITOR
206 void
207 stmonitor(PLAYER *pp)
208 {
209 int line;
210 PLAYER *npp;
211
212 memcpy(pp->p_maze, Maze, sizeof Maze);
213
214 drawmaze(pp);
215
216 (void) snprintf(Buf, sizeof(Buf), "%5.5s%c%-10.10s %c", " ",
217 stat_char(pp),
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);
223 }
224 for (npp = Monitor; npp < End_monitor; npp++) {
225 cgoto(npp, line, STAT_NAME_COL);
226 outstr(npp, Buf, STAT_NAME_LEN);
227 }
228
229 sendcom(pp, REFRESH);
230 sendcom(pp, READY, 0);
231 (void) fflush(pp->p_output);
232 }
233 #endif
234
235 void
236 stplayer(PLAYER *newpp, int enter_status)
237 {
238 int x, y;
239 PLAYER *pp;
240
241 Nplayer++;
242
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];
253 }
254 for ( ; y < HEIGHT; y++)
255 for (x = 0; x < WIDTH; x++)
256 newpp->p_maze[y][x] = Maze[y][x];
257
258 do {
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;
263 newpp->p_x = x;
264 newpp->p_y = y;
265 newpp->p_undershot = FALSE;
266
267 #ifdef FLY
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;
273 }
274 else
275 #endif
276 {
277 newpp->p_flying = -1;
278 newpp->p_face = rand_dir();
279 }
280 newpp->p_damage = 0;
281 newpp->p_damcap = MAXDAM;
282 newpp->p_nchar = 0;
283 newpp->p_ncount = 0;
284 newpp->p_nexec = 0;
285 newpp->p_ammo = ISHOTS;
286 #ifdef BOOTS
287 newpp->p_nboots = 0;
288 #endif
289 if (enter_status == Q_SCAN) {
290 newpp->p_scan = SCANLEN;
291 newpp->p_cloak = 0;
292 }
293 else {
294 newpp->p_scan = 0;
295 newpp->p_cloak = CLOAKLEN;
296 }
297 newpp->p_ncshot = 0;
298
299 do {
300 x = rand_num(WIDTH - 1) + 1;
301 y = rand_num(HEIGHT - 1) + 1;
302 } while (Maze[y][x] != SPACE);
303 Maze[y][x] = GMINE;
304 #ifdef MONITOR
305 for (pp = Monitor; pp < End_monitor; pp++)
306 check(pp, y, x);
307 #endif
308
309 do {
310 x = rand_num(WIDTH - 1) + 1;
311 y = rand_num(HEIGHT - 1) + 1;
312 } while (Maze[y][x] != SPACE);
313 Maze[y][x] = MINE;
314 #ifdef MONITOR
315 for (pp = Monitor; pp < End_monitor; pp++)
316 check(pp, y, x);
317 #endif
318
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++) {
325 if (pp != newpp) {
326 char smallbuf[16];
327
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),
333 "%3d", pp->p_ammo);
334 cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
335 outstr(pp, smallbuf, 3);
336 }
337 }
338 #ifdef MONITOR
339 for (pp = Monitor; pp < End_monitor; pp++) {
340 cgoto(pp, y, STAT_NAME_COL);
341 outstr(pp, Buf, STAT_NAME_LEN);
342 }
343 #endif
344
345 drawmaze(newpp);
346 drawplayer(newpp, TRUE);
347 look(newpp);
348 #ifdef FLY
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);
352 #endif
353 sendcom(newpp, REFRESH);
354 sendcom(newpp, READY, 0);
355 (void) fflush(newpp->p_output);
356 }
357
358 /*
359 * rand_dir:
360 * Return a random direction
361 */
362 int
363 rand_dir(void)
364 {
365 switch (rand_num(4)) {
366 case 0:
367 return LEFTS;
368 case 1:
369 return RIGHT;
370 case 2:
371 return BELOW;
372 case 3:
373 return ABOVE;
374 }
375 /* NOTREACHED */
376 return(-1);
377 }
378
379 /*
380 * get_ident:
381 * Get the score structure of a player
382 */
383 IDENT *
384 get_ident(uint32_t machine, uint32_t uid, char *name, char team)
385 {
386 IDENT *ip;
387 static IDENT punt;
388
389 for (ip = Scores; ip != NULL; ip = ip->i_next)
390 if (ip->i_machine == machine
391 && ip->i_uid == uid
392 && ip->i_team == team
393 && strncmp(ip->i_name, name, NAMELEN) == 0)
394 break;
395
396 if (ip != NULL) {
397 if (ip->i_entries < SCOREDECAY)
398 ip->i_entries++;
399 else
400 ip->i_kills = (ip->i_kills * (SCOREDECAY - 1))
401 / SCOREDECAY;
402 ip->i_score = ip->i_kills / (double) ip->i_entries;
403 }
404 else {
405 ip = malloc(sizeof(*ip));
406 if (ip == NULL) {
407 /* Fourth down, time to punt */
408 ip = &punt;
409 }
410 ip->i_machine = machine;
411 ip->i_team = team;
412 ip->i_uid = uid;
413 strncpy(ip->i_name, name, NAMELEN);
414 ip->i_kills = 0;
415 ip->i_entries = 1;
416 ip->i_score = 0;
417 ip->i_absorbed = 0;
418 ip->i_faced = 0;
419 ip->i_shot = 0;
420 ip->i_robbed = 0;
421 ip->i_slime = 0;
422 ip->i_missed = 0;
423 ip->i_ducked = 0;
424 ip->i_gkills = ip->i_bkills = ip->i_deaths = 0;
425 ip->i_stillb = ip->i_saved = 0;
426 ip->i_next = Scores;
427 Scores = ip;
428 }
429
430 return ip;
431 }