execute.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. /* $NetBSD: execute.c,v 1.4 2004/01/27 20:30:29 jsm 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: execute.c,v 1.4 2004/01/27 20:30:29 jsm Exp $");
  35. #endif /* not lint */
  36. # include <stdlib.h>
  37. # include "hunt.h"
  38. static void cloak(PLAYER *);
  39. static void face(PLAYER *, int);
  40. static void fire(PLAYER *, int);
  41. static void fire_slime(PLAYER *, int);
  42. static void move_player(PLAYER *, int);
  43. static void pickup(PLAYER *, int, int, int, int);
  44. static void scan(PLAYER *);
  45. # ifdef MONITOR
  46. /*
  47. * mon_execute:
  48. * Execute a single monitor command
  49. */
  50. void
  51. mon_execute(pp)
  52. PLAYER *pp;
  53. {
  54. char ch;
  55. ch = pp->p_cbuf[pp->p_ncount++];
  56. switch (ch) {
  57. case CTRL('L'):
  58. sendcom(pp, REDRAW);
  59. break;
  60. case 'q':
  61. (void) strcpy(pp->p_death, "| Quit |");
  62. break;
  63. }
  64. }
  65. # endif
  66. /*
  67. * execute:
  68. * Execute a single command
  69. */
  70. void
  71. execute(pp)
  72. PLAYER *pp;
  73. {
  74. char ch;
  75. ch = pp->p_cbuf[pp->p_ncount++];
  76. # ifdef FLY
  77. if (pp->p_flying >= 0) {
  78. switch (ch) {
  79. case CTRL('L'):
  80. sendcom(pp, REDRAW);
  81. break;
  82. case 'q':
  83. (void) strcpy(pp->p_death, "| Quit |");
  84. break;
  85. }
  86. return;
  87. }
  88. # endif
  89. switch (ch) {
  90. case CTRL('L'):
  91. sendcom(pp, REDRAW);
  92. break;
  93. case 'h':
  94. move_player(pp, LEFTS);
  95. break;
  96. case 'H':
  97. face(pp, LEFTS);
  98. break;
  99. case 'j':
  100. move_player(pp, BELOW);
  101. break;
  102. case 'J':
  103. face(pp, BELOW);
  104. break;
  105. case 'k':
  106. move_player(pp, ABOVE);
  107. break;
  108. case 'K':
  109. face(pp, ABOVE);
  110. break;
  111. case 'l':
  112. move_player(pp, RIGHT);
  113. break;
  114. case 'L':
  115. face(pp, RIGHT);
  116. break;
  117. case 'f':
  118. case '1':
  119. fire(pp, 0); /* SHOT */
  120. break;
  121. case 'g':
  122. case '2':
  123. fire(pp, 1); /* GRENADE */
  124. break;
  125. case 'F':
  126. case '3':
  127. fire(pp, 2); /* SATCHEL */
  128. break;
  129. case 'G':
  130. case '4':
  131. fire(pp, 3); /* 7x7 BOMB */
  132. break;
  133. case '5':
  134. fire(pp, 4); /* 9x9 BOMB */
  135. break;
  136. case '6':
  137. fire(pp, 5); /* 11x11 BOMB */
  138. break;
  139. case '7':
  140. fire(pp, 6); /* 13x13 BOMB */
  141. break;
  142. case '8':
  143. fire(pp, 7); /* 15x15 BOMB */
  144. break;
  145. case '9':
  146. fire(pp, 8); /* 17x17 BOMB */
  147. break;
  148. case '0':
  149. fire(pp, 9); /* 19x19 BOMB */
  150. break;
  151. case '@':
  152. fire(pp, 10); /* 21x21 BOMB */
  153. break;
  154. # ifdef OOZE
  155. case 'o':
  156. fire_slime(pp, 0); /* SLIME */
  157. break;
  158. case 'O':
  159. fire_slime(pp, 1); /* SSLIME */
  160. break;
  161. case 'p':
  162. fire_slime(pp, 2);
  163. break;
  164. case 'P':
  165. fire_slime(pp, 3);
  166. break;
  167. # endif
  168. case 's':
  169. scan(pp);
  170. break;
  171. case 'c':
  172. cloak(pp);
  173. break;
  174. case 'q':
  175. (void) strcpy(pp->p_death, "| Quit |");
  176. break;
  177. }
  178. }
  179. /*
  180. * move_player:
  181. * Execute a move in the given direction
  182. */
  183. static void
  184. move_player(pp, dir)
  185. PLAYER *pp;
  186. int dir;
  187. {
  188. PLAYER *newp;
  189. int x, y;
  190. FLAG moved;
  191. BULLET *bp;
  192. y = pp->p_y;
  193. x = pp->p_x;
  194. switch (dir) {
  195. case LEFTS:
  196. x--;
  197. break;
  198. case RIGHT:
  199. x++;
  200. break;
  201. case ABOVE:
  202. y--;
  203. break;
  204. case BELOW:
  205. y++;
  206. break;
  207. }
  208. moved = FALSE;
  209. switch (Maze[y][x]) {
  210. case SPACE:
  211. # ifdef RANDOM
  212. case DOOR:
  213. # endif
  214. moved = TRUE;
  215. break;
  216. case WALL1:
  217. case WALL2:
  218. case WALL3:
  219. # ifdef REFLECT
  220. case WALL4:
  221. case WALL5:
  222. # endif
  223. break;
  224. case MINE:
  225. case GMINE:
  226. if (dir == pp->p_face)
  227. pickup(pp, y, x, 2, Maze[y][x]);
  228. else if (opposite(dir, pp->p_face))
  229. pickup(pp, y, x, 95, Maze[y][x]);
  230. else
  231. pickup(pp, y, x, 50, Maze[y][x]);
  232. Maze[y][x] = SPACE;
  233. moved = TRUE;
  234. break;
  235. case SHOT:
  236. case GRENADE:
  237. case SATCHEL:
  238. case BOMB:
  239. # ifdef OOZE
  240. case SLIME:
  241. # endif
  242. # ifdef DRONE
  243. case DSHOT:
  244. # endif
  245. bp = is_bullet(y, x);
  246. if (bp != NULL)
  247. bp->b_expl = TRUE;
  248. Maze[y][x] = SPACE;
  249. moved = TRUE;
  250. break;
  251. case LEFTS:
  252. case RIGHT:
  253. case ABOVE:
  254. case BELOW:
  255. if (dir != pp->p_face)
  256. sendcom(pp, BELL);
  257. else {
  258. newp = play_at(y, x);
  259. checkdam(newp, pp, pp->p_ident, STABDAM, KNIFE);
  260. }
  261. break;
  262. # ifdef FLY
  263. case FLYER:
  264. newp = play_at(y, x);
  265. message(newp, "Oooh, there's a short guy waving at you!");
  266. message(pp, "You couldn't quite reach him!");
  267. break;
  268. # endif
  269. # ifdef BOOTS
  270. case BOOT:
  271. case BOOT_PAIR:
  272. if (Maze[y][x] == BOOT)
  273. pp->p_nboots++;
  274. else
  275. pp->p_nboots += 2;
  276. for (newp = Boot; newp < &Boot[NBOOTS]; newp++) {
  277. if (newp->p_flying < 0)
  278. continue;
  279. if (newp->p_y == y && newp->p_x == x) {
  280. newp->p_flying = -1;
  281. if (newp->p_undershot)
  282. fixshots(y, x, newp->p_over);
  283. }
  284. }
  285. if (pp->p_nboots == 2)
  286. message(pp, "Wow! A pair of boots!");
  287. else
  288. message(pp, "You can hobble around on one boot.");
  289. Maze[y][x] = SPACE;
  290. moved = TRUE;
  291. break;
  292. # endif
  293. }
  294. if (moved) {
  295. if (pp->p_ncshot > 0)
  296. if (--pp->p_ncshot == MAXNCSHOT) {
  297. cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
  298. outstr(pp, " ok", 3);
  299. }
  300. if (pp->p_undershot) {
  301. fixshots(pp->p_y, pp->p_x, pp->p_over);
  302. pp->p_undershot = FALSE;
  303. }
  304. drawplayer(pp, FALSE);
  305. pp->p_over = Maze[y][x];
  306. pp->p_y = y;
  307. pp->p_x = x;
  308. drawplayer(pp, TRUE);
  309. }
  310. }
  311. /*
  312. * face:
  313. * Change the direction the player is facing
  314. */
  315. static void
  316. face(pp, dir)
  317. PLAYER *pp;
  318. int dir;
  319. {
  320. if (pp->p_face != dir) {
  321. pp->p_face = dir;
  322. drawplayer(pp, TRUE);
  323. }
  324. }
  325. /*
  326. * fire:
  327. * Fire a shot of the given type in the given direction
  328. */
  329. static void
  330. fire(pp, req_index)
  331. PLAYER *pp;
  332. int req_index;
  333. {
  334. if (pp == NULL)
  335. return;
  336. # ifdef DEBUG
  337. if (req_index < 0 || req_index >= MAXBOMB)
  338. message(pp, "What you do?");
  339. # endif
  340. while (req_index >= 0 && pp->p_ammo < shot_req[req_index])
  341. req_index--;
  342. if (req_index < 0) {
  343. message(pp, "Not enough charges.");
  344. return;
  345. }
  346. if (pp->p_ncshot > MAXNCSHOT)
  347. return;
  348. if (pp->p_ncshot++ == MAXNCSHOT) {
  349. cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
  350. outstr(pp, " ", 3);
  351. }
  352. pp->p_ammo -= shot_req[req_index];
  353. (void) sprintf(Buf, "%3d", pp->p_ammo);
  354. cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
  355. outstr(pp, Buf, 3);
  356. add_shot(shot_type[req_index], pp->p_y, pp->p_x, pp->p_face,
  357. shot_req[req_index], pp, FALSE, pp->p_face);
  358. pp->p_undershot = TRUE;
  359. /*
  360. * Show the object to everyone
  361. */
  362. showexpl(pp->p_y, pp->p_x, shot_type[req_index]);
  363. for (pp = Player; pp < End_player; pp++)
  364. sendcom(pp, REFRESH);
  365. # ifdef MONITOR
  366. for (pp = Monitor; pp < End_monitor; pp++)
  367. sendcom(pp, REFRESH);
  368. # endif
  369. }
  370. # ifdef OOZE
  371. /*
  372. * fire_slime:
  373. * Fire a slime shot in the given direction
  374. */
  375. static void
  376. fire_slime(pp, req_index)
  377. PLAYER *pp;
  378. int req_index;
  379. {
  380. if (pp == NULL)
  381. return;
  382. # ifdef DEBUG
  383. if (req_index < 0 || req_index >= MAXSLIME)
  384. message(pp, "What you do?");
  385. # endif
  386. while (req_index >= 0 && pp->p_ammo < slime_req[req_index])
  387. req_index--;
  388. if (req_index < 0) {
  389. message(pp, "Not enough charges.");
  390. return;
  391. }
  392. if (pp->p_ncshot > MAXNCSHOT)
  393. return;
  394. if (pp->p_ncshot++ == MAXNCSHOT) {
  395. cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
  396. outstr(pp, " ", 3);
  397. }
  398. pp->p_ammo -= slime_req[req_index];
  399. (void) sprintf(Buf, "%3d", pp->p_ammo);
  400. cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
  401. outstr(pp, Buf, 3);
  402. add_shot(SLIME, pp->p_y, pp->p_x, pp->p_face,
  403. slime_req[req_index] * SLIME_FACTOR, pp, FALSE, pp->p_face);
  404. pp->p_undershot = TRUE;
  405. /*
  406. * Show the object to everyone
  407. */
  408. showexpl(pp->p_y, pp->p_x, SLIME);
  409. for (pp = Player; pp < End_player; pp++)
  410. sendcom(pp, REFRESH);
  411. # ifdef MONITOR
  412. for (pp = Monitor; pp < End_monitor; pp++)
  413. sendcom(pp, REFRESH);
  414. # endif
  415. }
  416. # endif
  417. /*
  418. * add_shot:
  419. * Create a shot with the given properties
  420. */
  421. void
  422. add_shot(type, y, x, face, charge, owner, expl, over)
  423. int type;
  424. int y, x;
  425. char face;
  426. int charge;
  427. PLAYER *owner;
  428. int expl;
  429. char over;
  430. {
  431. BULLET *bp;
  432. int size;
  433. switch (type) {
  434. case SHOT:
  435. case MINE:
  436. size = 1;
  437. break;
  438. case GRENADE:
  439. case GMINE:
  440. size = 2;
  441. break;
  442. case SATCHEL:
  443. size = 3;
  444. break;
  445. case BOMB:
  446. for (size = 3; size < MAXBOMB; size++)
  447. if (shot_req[size] >= charge)
  448. break;
  449. size++;
  450. break;
  451. default:
  452. size = 0;
  453. break;
  454. }
  455. bp = create_shot(type, y, x, face, charge, size, owner,
  456. (owner == NULL) ? NULL : owner->p_ident, expl, over);
  457. bp->b_next = Bullets;
  458. Bullets = bp;
  459. }
  460. BULLET *
  461. create_shot(type, y, x, face, charge, size, owner, score, expl, over)
  462. int type;
  463. int y, x;
  464. char face;
  465. int charge;
  466. int size;
  467. PLAYER *owner;
  468. IDENT *score;
  469. int expl;
  470. char over;
  471. {
  472. BULLET *bp;
  473. bp = (BULLET *) malloc(sizeof (BULLET)); /* NOSTRICT */
  474. if (bp == NULL) {
  475. if (owner != NULL)
  476. message(owner, "Out of memory");
  477. return NULL;
  478. }
  479. bp->b_face = face;
  480. bp->b_x = x;
  481. bp->b_y = y;
  482. bp->b_charge = charge;
  483. bp->b_owner = owner;
  484. bp->b_score = score;
  485. bp->b_type = type;
  486. bp->b_size = size;
  487. bp->b_expl = expl;
  488. bp->b_over = over;
  489. bp->b_next = NULL;
  490. return bp;
  491. }
  492. /*
  493. * cloak:
  494. * Turn on or increase length of a cloak
  495. */
  496. static void
  497. cloak(pp)
  498. PLAYER *pp;
  499. {
  500. if (pp->p_ammo <= 0) {
  501. message(pp, "No more charges");
  502. return;
  503. }
  504. # ifdef BOOTS
  505. if (pp->p_nboots > 0) {
  506. message(pp, "Boots are too noisy to cloak!");
  507. return;
  508. }
  509. # endif
  510. (void) sprintf(Buf, "%3d", --pp->p_ammo);
  511. cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
  512. outstr(pp, Buf, 3);
  513. pp->p_cloak += CLOAKLEN;
  514. if (pp->p_scan >= 0)
  515. pp->p_scan = -1;
  516. showstat(pp);
  517. }
  518. /*
  519. * scan:
  520. * Turn on or increase length of a scan
  521. */
  522. static void
  523. scan(pp)
  524. PLAYER *pp;
  525. {
  526. if (pp->p_ammo <= 0) {
  527. message(pp, "No more charges");
  528. return;
  529. }
  530. (void) sprintf(Buf, "%3d", --pp->p_ammo);
  531. cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
  532. outstr(pp, Buf, 3);
  533. pp->p_scan += SCANLEN;
  534. if (pp->p_cloak >= 0)
  535. pp->p_cloak = -1;
  536. showstat(pp);
  537. }
  538. /*
  539. * pickup:
  540. * check whether the object blew up or whether he picked it up
  541. */
  542. void
  543. pickup(pp, y, x, prob, obj)
  544. PLAYER *pp;
  545. int y, x;
  546. int prob;
  547. int obj;
  548. {
  549. int req;
  550. switch (obj) {
  551. case MINE:
  552. req = BULREQ;
  553. break;
  554. case GMINE:
  555. req = GRENREQ;
  556. break;
  557. default:
  558. abort();
  559. }
  560. if (rand_num(100) < prob)
  561. add_shot(obj, y, x, LEFTS, req, (PLAYER *) NULL,
  562. TRUE, pp->p_face);
  563. else {
  564. pp->p_ammo += req;
  565. (void) sprintf(Buf, "%3d", pp->p_ammo);
  566. cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
  567. outstr(pp, Buf, 3);
  568. }
  569. }