answer.c 9.9 KB

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