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