]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - hunt/huntd/answer.c
Add (unsigned char) cast to ctype functions
[bsdgames-darwin.git] / hunt / huntd / answer.c
1 /* $NetBSD: answer.c,v 1.7 2004/11/05 21:30:32 dsl 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.7 2004/11/05 21:30:32 dsl 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()
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 int socklen;
59 static u_long machine;
60 static u_int32_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, (char *) &version, LONGLEN);
94 (void) read(newsock, (char *) &uid, LONGLEN);
95 uid = ntohl((unsigned long) uid);
96 (void) read(newsock, name, NAMELEN);
97 (void) read(newsock, &team, 1);
98 (void) read(newsock, (char *) &enter_status, LONGLEN);
99 enter_status = ntohl((unsigned long) enter_status);
100 (void) read(newsock, Ttyname, NAMELEN);
101 (void) read(newsock, (char *) &mode, sizeof mode);
102 mode = ntohl(mode);
103
104 /*
105 * Turn off blocking I/O, so a slow or dead terminal won't stop
106 * the game. All subsequent reads check how many bytes they read.
107 */
108 flags = fcntl(newsock, F_GETFL, 0);
109 flags |= O_NDELAY;
110 (void) fcntl(newsock, F_SETFL, flags);
111
112 /*
113 * Make sure the name contains only printable characters
114 * since we use control characters for cursor control
115 * between driver and player processes
116 */
117 for (cp1 = cp2 = name; *cp1 != '\0'; cp1++)
118 if (isprint((unsigned char)*cp1) || *cp1 == ' ')
119 *cp2++ = *cp1;
120 *cp2 = '\0';
121
122 # ifdef INTERNET
123 if (mode == C_MESSAGE) {
124 char buf[BUFSIZ + 1];
125 int n;
126
127 if (team == ' ')
128 (void) sprintf(buf, "%s: ", name);
129 else
130 (void) sprintf(buf, "%s[%c]: ", name, team);
131 n = strlen(buf);
132 for (pp = Player; pp < End_player; pp++) {
133 cgoto(pp, HEIGHT, 0);
134 outstr(pp, buf, n);
135 }
136 while ((n = read(newsock, buf, BUFSIZ)) > 0)
137 for (pp = Player; pp < End_player; pp++)
138 outstr(pp, buf, n);
139 for (pp = Player; pp < End_player; pp++) {
140 ce(pp);
141 sendcom(pp, REFRESH);
142 sendcom(pp, READY, 0);
143 (void) fflush(pp->p_output);
144 }
145 (void) close(newsock);
146 return FALSE;
147 }
148 else
149 # endif
150 # ifdef MONITOR
151 if (mode == C_MONITOR)
152 if (End_monitor < &Monitor[MAXMON]) {
153 pp = End_monitor++;
154 i = pp - Monitor + MAXPL + 3;
155 } else {
156 socklen = 0;
157 (void) write(newsock, (char *) &socklen,
158 sizeof socklen);
159 (void) close(newsock);
160 return FALSE;
161 }
162 else
163 # endif
164 if (End_player < &Player[MAXPL]) {
165 pp = End_player++;
166 i = pp - Player + 3;
167 } else {
168 socklen = 0;
169 (void) write(newsock, (char *) &socklen,
170 sizeof socklen);
171 (void) close(newsock);
172 return FALSE;
173 }
174
175 #ifdef MONITOR
176 if (mode == C_MONITOR && team == ' ')
177 team = '*';
178 #endif
179 pp->p_ident = get_ident(machine, uid, name, team);
180 pp->p_output = fdopen(newsock, "w");
181 pp->p_death[0] = '\0';
182 pp->p_fd = newsock;
183 fdset[i].fd = newsock;
184 fdset[i].events = POLLIN;
185
186 pp->p_y = 0;
187 pp->p_x = 0;
188
189 # ifdef MONITOR
190 if (mode == C_MONITOR)
191 stmonitor(pp);
192 else
193 # endif
194 stplayer(pp, enter_status);
195 return TRUE;
196 }
197
198 # ifdef MONITOR
199 void
200 stmonitor(pp)
201 PLAYER *pp;
202 {
203 int line;
204 PLAYER *npp;
205
206 memcpy(pp->p_maze, Maze, sizeof Maze);
207
208 drawmaze(pp);
209
210 (void) sprintf(Buf, "%5.5s%c%-10.10s %c", " ", stat_char(pp),
211 pp->p_ident->i_name, pp->p_ident->i_team);
212 line = STAT_MON_ROW + 1 + (pp - Monitor);
213 for (npp = Player; npp < End_player; npp++) {
214 cgoto(npp, line, STAT_NAME_COL);
215 outstr(npp, Buf, STAT_NAME_LEN);
216 }
217 for (npp = Monitor; npp < End_monitor; npp++) {
218 cgoto(npp, line, STAT_NAME_COL);
219 outstr(npp, Buf, STAT_NAME_LEN);
220 }
221
222 sendcom(pp, REFRESH);
223 sendcom(pp, READY, 0);
224 (void) fflush(pp->p_output);
225 }
226 # endif
227
228 void
229 stplayer(newpp, enter_status)
230 PLAYER *newpp;
231 int enter_status;
232 {
233 int x, y;
234 PLAYER *pp;
235
236 Nplayer++;
237
238 for (y = 0; y < UBOUND; y++)
239 for (x = 0; x < WIDTH; x++)
240 newpp->p_maze[y][x] = Maze[y][x];
241 for ( ; y < DBOUND; y++) {
242 for (x = 0; x < LBOUND; x++)
243 newpp->p_maze[y][x] = Maze[y][x];
244 for ( ; x < RBOUND; x++)
245 newpp->p_maze[y][x] = SPACE;
246 for ( ; x < WIDTH; x++)
247 newpp->p_maze[y][x] = Maze[y][x];
248 }
249 for ( ; y < HEIGHT; y++)
250 for (x = 0; x < WIDTH; x++)
251 newpp->p_maze[y][x] = Maze[y][x];
252
253 do {
254 x = rand_num(WIDTH - 1) + 1;
255 y = rand_num(HEIGHT - 1) + 1;
256 } while (Maze[y][x] != SPACE);
257 newpp->p_over = SPACE;
258 newpp->p_x = x;
259 newpp->p_y = y;
260 newpp->p_undershot = FALSE;
261
262 # ifdef FLY
263 if (enter_status == Q_FLY) {
264 newpp->p_flying = rand_num(20);
265 newpp->p_flyx = 2 * rand_num(6) - 5;
266 newpp->p_flyy = 2 * rand_num(6) - 5;
267 newpp->p_face = FLYER;
268 }
269 else
270 # endif
271 {
272 newpp->p_flying = -1;
273 newpp->p_face = rand_dir();
274 }
275 newpp->p_damage = 0;
276 newpp->p_damcap = MAXDAM;
277 newpp->p_nchar = 0;
278 newpp->p_ncount = 0;
279 newpp->p_nexec = 0;
280 newpp->p_ammo = ISHOTS;
281 # ifdef BOOTS
282 newpp->p_nboots = 0;
283 # endif
284 if (enter_status == Q_SCAN) {
285 newpp->p_scan = SCANLEN;
286 newpp->p_cloak = 0;
287 }
288 else {
289 newpp->p_scan = 0;
290 newpp->p_cloak = CLOAKLEN;
291 }
292 newpp->p_ncshot = 0;
293
294 do {
295 x = rand_num(WIDTH - 1) + 1;
296 y = rand_num(HEIGHT - 1) + 1;
297 } while (Maze[y][x] != SPACE);
298 Maze[y][x] = GMINE;
299 # ifdef MONITOR
300 for (pp = Monitor; pp < End_monitor; pp++)
301 check(pp, y, x);
302 # endif
303
304 do {
305 x = rand_num(WIDTH - 1) + 1;
306 y = rand_num(HEIGHT - 1) + 1;
307 } while (Maze[y][x] != SPACE);
308 Maze[y][x] = MINE;
309 # ifdef MONITOR
310 for (pp = Monitor; pp < End_monitor; pp++)
311 check(pp, y, x);
312 # endif
313
314 (void) sprintf(Buf, "%5.2f%c%-10.10s %c", newpp->p_ident->i_score,
315 stat_char(newpp), newpp->p_ident->i_name,
316 newpp->p_ident->i_team);
317 y = STAT_PLAY_ROW + 1 + (newpp - Player);
318 for (pp = Player; pp < End_player; pp++) {
319 if (pp != newpp) {
320 char smallbuf[10];
321
322 pp->p_ammo += NSHOTS;
323 newpp->p_ammo += NSHOTS;
324 cgoto(pp, y, STAT_NAME_COL);
325 outstr(pp, Buf, STAT_NAME_LEN);
326 (void) sprintf(smallbuf, "%3d", pp->p_ammo);
327 cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
328 outstr(pp, smallbuf, 3);
329 }
330 }
331 # ifdef MONITOR
332 for (pp = Monitor; pp < End_monitor; pp++) {
333 cgoto(pp, y, STAT_NAME_COL);
334 outstr(pp, Buf, STAT_NAME_LEN);
335 }
336 # endif
337
338 drawmaze(newpp);
339 drawplayer(newpp, TRUE);
340 look(newpp);
341 # ifdef FLY
342 if (enter_status == Q_FLY)
343 /* Make sure that the position you enter in will be erased */
344 showexpl(newpp->p_y, newpp->p_x, FLYER);
345 # endif
346 sendcom(newpp, REFRESH);
347 sendcom(newpp, READY, 0);
348 (void) fflush(newpp->p_output);
349 }
350
351 /*
352 * rand_dir:
353 * Return a random direction
354 */
355 int
356 rand_dir()
357 {
358 switch (rand_num(4)) {
359 case 0:
360 return LEFTS;
361 case 1:
362 return RIGHT;
363 case 2:
364 return BELOW;
365 case 3:
366 return ABOVE;
367 }
368 /* NOTREACHED */
369 return(-1);
370 }
371
372 /*
373 * get_ident:
374 * Get the score structure of a player
375 */
376 IDENT *
377 get_ident(machine, uid, name, team)
378 u_long machine;
379 u_long uid;
380 char *name;
381 char team;
382 {
383 IDENT *ip;
384 static IDENT punt;
385
386 for (ip = Scores; ip != NULL; ip = ip->i_next)
387 if (ip->i_machine == machine
388 && ip->i_uid == uid
389 && ip->i_team == team
390 && strncmp(ip->i_name, name, NAMELEN) == 0)
391 break;
392
393 if (ip != NULL) {
394 if (ip->i_entries < SCOREDECAY)
395 ip->i_entries++;
396 else
397 ip->i_kills = (ip->i_kills * (SCOREDECAY - 1))
398 / SCOREDECAY;
399 ip->i_score = ip->i_kills / (double) ip->i_entries;
400 }
401 else {
402 ip = (IDENT *) malloc(sizeof (IDENT));
403 if (ip == NULL) {
404 /* Fourth down, time to punt */
405 ip = &punt;
406 }
407 ip->i_machine = machine;
408 ip->i_team = team;
409 ip->i_uid = uid;
410 strncpy(ip->i_name, name, NAMELEN);
411 ip->i_kills = 0;
412 ip->i_entries = 1;
413 ip->i_score = 0;
414 ip->i_absorbed = 0;
415 ip->i_faced = 0;
416 ip->i_shot = 0;
417 ip->i_robbed = 0;
418 ip->i_slime = 0;
419 ip->i_missed = 0;
420 ip->i_ducked = 0;
421 ip->i_gkills = ip->i_bkills = ip->i_deaths = 0;
422 ip->i_stillb = ip->i_saved = 0;
423 ip->i_next = Scores;
424 Scores = ip;
425 }
426
427 return ip;
428 }