]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - hunt/huntd/answer.c
Yet Another Monster Commit:
[bsdgames-darwin.git] / hunt / huntd / answer.c
1 /* $NetBSD: answer.c,v 1.3 1997/10/10 16:32:50 lukem Exp $ */
2 /*
3 * Hunt
4 * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
5 * San Francisco, California
6 */
7
8 #include <sys/cdefs.h>
9 #ifndef lint
10 __RCSID("$NetBSD: answer.c,v 1.3 1997/10/10 16:32:50 lukem Exp $");
11 #endif /* not lint */
12
13 # include <ctype.h>
14 # include <errno.h>
15 # include <fcntl.h>
16 # include <stdlib.h>
17 # include <unistd.h>
18 # include "hunt.h"
19
20 # define SCOREDECAY 15
21
22 static char Ttyname[NAMELEN];
23
24 int
25 answer()
26 {
27 PLAYER *pp;
28 int newsock;
29 static u_long mode;
30 static char name[NAMELEN];
31 static char team;
32 static int enter_status;
33 static int socklen;
34 static u_long machine;
35 static u_long uid;
36 static SOCKET sockstruct;
37 char *cp1, *cp2;
38 int flags;
39 long version;
40
41 # ifdef INTERNET
42 socklen = sizeof sockstruct;
43 # else
44 socklen = sizeof sockstruct - 1;
45 # endif
46 errno = 0;
47 newsock = accept(Socket, (struct sockaddr *) &sockstruct, &socklen);
48 if (newsock < 0)
49 {
50 if (errno == EINTR)
51 return FALSE;
52 # ifdef LOG
53 syslog(LOG_ERR, "accept: %m");
54 # else
55 perror("accept");
56 # endif
57 cleanup(1);
58 }
59
60 # ifdef INTERNET
61 machine = ntohl(((struct sockaddr_in *) &sockstruct)->sin_addr.s_addr);
62 # else
63 if (machine == 0)
64 machine = gethostid();
65 # endif
66 version = htonl((u_int32_t) HUNT_VERSION);
67 (void) write(newsock, (char *) &version, LONGLEN);
68 (void) read(newsock, (char *) &uid, LONGLEN);
69 uid = ntohl((unsigned long) uid);
70 (void) read(newsock, name, NAMELEN);
71 (void) read(newsock, &team, 1);
72 (void) read(newsock, (char *) &enter_status, LONGLEN);
73 enter_status = ntohl((unsigned long) enter_status);
74 (void) read(newsock, Ttyname, NAMELEN);
75 (void) read(newsock, (char *) &mode, sizeof mode);
76 mode = ntohl(mode);
77
78 /*
79 * Turn off blocking I/O, so a slow or dead terminal won't stop
80 * the game. All subsequent reads check how many bytes they read.
81 */
82 flags = fcntl(newsock, F_GETFL, 0);
83 flags |= O_NDELAY;
84 (void) fcntl(newsock, F_SETFL, flags);
85
86 /*
87 * Make sure the name contains only printable characters
88 * since we use control characters for cursor control
89 * between driver and player processes
90 */
91 for (cp1 = cp2 = name; *cp1 != '\0'; cp1++)
92 if (isprint(*cp1) || *cp1 == ' ')
93 *cp2++ = *cp1;
94 *cp2 = '\0';
95
96 # ifdef INTERNET
97 if (mode == C_MESSAGE) {
98 char buf[BUFSIZ + 1];
99 int n;
100
101 if (team == ' ')
102 (void) sprintf(buf, "%s: ", name);
103 else
104 (void) sprintf(buf, "%s[%c]: ", name, team);
105 n = strlen(buf);
106 for (pp = Player; pp < End_player; pp++) {
107 cgoto(pp, HEIGHT, 0);
108 outstr(pp, buf, n);
109 }
110 while ((n = read(newsock, buf, BUFSIZ)) > 0)
111 for (pp = Player; pp < End_player; pp++)
112 outstr(pp, buf, n);
113 for (pp = Player; pp < End_player; pp++) {
114 ce(pp);
115 sendcom(pp, REFRESH);
116 sendcom(pp, READY, 0);
117 (void) fflush(pp->p_output);
118 }
119 (void) close(newsock);
120 return FALSE;
121 }
122 else
123 # endif
124 # ifdef MONITOR
125 if (mode == C_MONITOR)
126 if (End_monitor < &Monitor[MAXMON])
127 pp = End_monitor++;
128 else {
129 socklen = 0;
130 (void) write(newsock, (char *) &socklen,
131 sizeof socklen);
132 (void) close(newsock);
133 return FALSE;
134 }
135 else
136 # endif
137 if (End_player < &Player[MAXPL])
138 pp = End_player++;
139 else {
140 socklen = 0;
141 (void) write(newsock, (char *) &socklen,
142 sizeof socklen);
143 (void) close(newsock);
144 return FALSE;
145 }
146
147 #ifdef MONITOR
148 if (mode == C_MONITOR && team == ' ')
149 team = '*';
150 #endif
151 pp->p_ident = get_ident(machine, uid, name, team);
152 pp->p_output = fdopen(newsock, "w");
153 pp->p_death[0] = '\0';
154 pp->p_fd = newsock;
155 FD_SET(pp->p_fd, &Fds_mask);
156 if (pp->p_fd >= Num_fds)
157 Num_fds = pp->p_fd + 1;
158
159 pp->p_y = 0;
160 pp->p_x = 0;
161
162 # ifdef MONITOR
163 if (mode == C_MONITOR)
164 stmonitor(pp);
165 else
166 # endif
167 stplayer(pp, enter_status);
168 return TRUE;
169 }
170
171 # ifdef MONITOR
172 void
173 stmonitor(pp)
174 PLAYER *pp;
175 {
176 int line;
177 PLAYER *npp;
178
179 memcpy(pp->p_maze, Maze, sizeof Maze);
180
181 drawmaze(pp);
182
183 (void) sprintf(Buf, "%5.5s%c%-10.10s %c", " ", stat_char(pp),
184 pp->p_ident->i_name, pp->p_ident->i_team);
185 line = STAT_MON_ROW + 1 + (pp - Monitor);
186 for (npp = Player; npp < End_player; npp++) {
187 cgoto(npp, line, STAT_NAME_COL);
188 outstr(npp, Buf, STAT_NAME_LEN);
189 }
190 for (npp = Monitor; npp < End_monitor; npp++) {
191 cgoto(npp, line, STAT_NAME_COL);
192 outstr(npp, Buf, STAT_NAME_LEN);
193 }
194
195 sendcom(pp, REFRESH);
196 sendcom(pp, READY, 0);
197 (void) fflush(pp->p_output);
198 }
199 # endif
200
201 void
202 stplayer(newpp, enter_status)
203 PLAYER *newpp;
204 int enter_status;
205 {
206 int x, y;
207 PLAYER *pp;
208
209 Nplayer++;
210
211 for (y = 0; y < UBOUND; y++)
212 for (x = 0; x < WIDTH; x++)
213 newpp->p_maze[y][x] = Maze[y][x];
214 for ( ; y < DBOUND; y++) {
215 for (x = 0; x < LBOUND; x++)
216 newpp->p_maze[y][x] = Maze[y][x];
217 for ( ; x < RBOUND; x++)
218 newpp->p_maze[y][x] = SPACE;
219 for ( ; x < WIDTH; x++)
220 newpp->p_maze[y][x] = Maze[y][x];
221 }
222 for ( ; y < HEIGHT; y++)
223 for (x = 0; x < WIDTH; x++)
224 newpp->p_maze[y][x] = Maze[y][x];
225
226 do {
227 x = rand_num(WIDTH - 1) + 1;
228 y = rand_num(HEIGHT - 1) + 1;
229 } while (Maze[y][x] != SPACE);
230 newpp->p_over = SPACE;
231 newpp->p_x = x;
232 newpp->p_y = y;
233 newpp->p_undershot = FALSE;
234
235 # ifdef FLY
236 if (enter_status == Q_FLY) {
237 newpp->p_flying = rand_num(20);
238 newpp->p_flyx = 2 * rand_num(6) - 5;
239 newpp->p_flyy = 2 * rand_num(6) - 5;
240 newpp->p_face = FLYER;
241 }
242 else
243 # endif
244 {
245 newpp->p_flying = -1;
246 newpp->p_face = rand_dir();
247 }
248 newpp->p_damage = 0;
249 newpp->p_damcap = MAXDAM;
250 newpp->p_nchar = 0;
251 newpp->p_ncount = 0;
252 newpp->p_nexec = 0;
253 newpp->p_ammo = ISHOTS;
254 # ifdef BOOTS
255 newpp->p_nboots = 0;
256 # endif
257 if (enter_status == Q_SCAN) {
258 newpp->p_scan = SCANLEN;
259 newpp->p_cloak = 0;
260 }
261 else {
262 newpp->p_scan = 0;
263 newpp->p_cloak = CLOAKLEN;
264 }
265 newpp->p_ncshot = 0;
266
267 do {
268 x = rand_num(WIDTH - 1) + 1;
269 y = rand_num(HEIGHT - 1) + 1;
270 } while (Maze[y][x] != SPACE);
271 Maze[y][x] = GMINE;
272 # ifdef MONITOR
273 for (pp = Monitor; pp < End_monitor; pp++)
274 check(pp, y, x);
275 # endif
276
277 do {
278 x = rand_num(WIDTH - 1) + 1;
279 y = rand_num(HEIGHT - 1) + 1;
280 } while (Maze[y][x] != SPACE);
281 Maze[y][x] = MINE;
282 # ifdef MONITOR
283 for (pp = Monitor; pp < End_monitor; pp++)
284 check(pp, y, x);
285 # endif
286
287 (void) sprintf(Buf, "%5.2f%c%-10.10s %c", newpp->p_ident->i_score,
288 stat_char(newpp), newpp->p_ident->i_name,
289 newpp->p_ident->i_team);
290 y = STAT_PLAY_ROW + 1 + (newpp - Player);
291 for (pp = Player; pp < End_player; pp++) {
292 if (pp != newpp) {
293 char smallbuf[10];
294
295 pp->p_ammo += NSHOTS;
296 newpp->p_ammo += NSHOTS;
297 cgoto(pp, y, STAT_NAME_COL);
298 outstr(pp, Buf, STAT_NAME_LEN);
299 (void) sprintf(smallbuf, "%3d", pp->p_ammo);
300 cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
301 outstr(pp, smallbuf, 3);
302 }
303 }
304 # ifdef MONITOR
305 for (pp = Monitor; pp < End_monitor; pp++) {
306 cgoto(pp, y, STAT_NAME_COL);
307 outstr(pp, Buf, STAT_NAME_LEN);
308 }
309 # endif
310
311 drawmaze(newpp);
312 drawplayer(newpp, TRUE);
313 look(newpp);
314 # ifdef FLY
315 if (enter_status == Q_FLY)
316 /* Make sure that the position you enter in will be erased */
317 showexpl(newpp->p_y, newpp->p_x, FLYER);
318 # endif
319 sendcom(newpp, REFRESH);
320 sendcom(newpp, READY, 0);
321 (void) fflush(newpp->p_output);
322 }
323
324 /*
325 * rand_dir:
326 * Return a random direction
327 */
328 int
329 rand_dir()
330 {
331 switch (rand_num(4)) {
332 case 0:
333 return LEFTS;
334 case 1:
335 return RIGHT;
336 case 2:
337 return BELOW;
338 case 3:
339 return ABOVE;
340 }
341 /* NOTREACHED */
342 return(-1);
343 }
344
345 /*
346 * get_ident:
347 * Get the score structure of a player
348 */
349 IDENT *
350 get_ident(machine, uid, name, team)
351 u_long machine;
352 u_long uid;
353 char *name;
354 char team;
355 {
356 IDENT *ip;
357 static IDENT punt;
358
359 for (ip = Scores; ip != NULL; ip = ip->i_next)
360 if (ip->i_machine == machine
361 && ip->i_uid == uid
362 && ip->i_team == team
363 && strncmp(ip->i_name, name, NAMELEN) == 0)
364 break;
365
366 if (ip != NULL) {
367 if (ip->i_entries < SCOREDECAY)
368 ip->i_entries++;
369 else
370 ip->i_kills = (ip->i_kills * (SCOREDECAY - 1))
371 / SCOREDECAY;
372 ip->i_score = ip->i_kills / (double) ip->i_entries;
373 }
374 else {
375 ip = (IDENT *) malloc(sizeof (IDENT));
376 if (ip == NULL) {
377 /* Fourth down, time to punt */
378 ip = &punt;
379 }
380 ip->i_machine = machine;
381 ip->i_team = team;
382 ip->i_uid = uid;
383 strncpy(ip->i_name, name, NAMELEN);
384 ip->i_kills = 0;
385 ip->i_entries = 1;
386 ip->i_score = 0;
387 ip->i_absorbed = 0;
388 ip->i_faced = 0;
389 ip->i_shot = 0;
390 ip->i_robbed = 0;
391 ip->i_slime = 0;
392 ip->i_missed = 0;
393 ip->i_ducked = 0;
394 ip->i_gkills = ip->i_bkills = ip->i_deaths = 0;
395 ip->i_stillb = ip->i_saved = 0;
396 ip->i_next = Scores;
397 Scores = ip;
398 }
399
400 return ip;
401 }