hack.do.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. /* $NetBSD: hack.do.c,v 1.7 2004/01/27 20:30:29 jsm Exp $ */
  2. /*
  3. * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
  4. * Amsterdam
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are
  9. * met:
  10. *
  11. * - Redistributions of source code must retain the above copyright notice,
  12. * this list of conditions and the following disclaimer.
  13. *
  14. * - Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. *
  18. * - Neither the name of the Stichting Centrum voor Wiskunde en
  19. * Informatica, nor the names of its contributors may be used to endorse or
  20. * promote products derived from this software without specific prior
  21. * written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  24. * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  25. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  26. * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
  27. * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  28. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  29. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  30. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  31. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  32. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  33. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34. */
  35. /*
  36. * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
  37. * All rights reserved.
  38. *
  39. * Redistribution and use in source and binary forms, with or without
  40. * modification, are permitted provided that the following conditions
  41. * are met:
  42. * 1. Redistributions of source code must retain the above copyright
  43. * notice, this list of conditions and the following disclaimer.
  44. * 2. Redistributions in binary form must reproduce the above copyright
  45. * notice, this list of conditions and the following disclaimer in the
  46. * documentation and/or other materials provided with the distribution.
  47. * 3. The name of the author may not be used to endorse or promote products
  48. * derived from this software without specific prior written permission.
  49. *
  50. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
  51. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  52. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  53. * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  54. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  55. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  56. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  57. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  58. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  59. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  60. */
  61. #include <sys/cdefs.h>
  62. #ifndef lint
  63. __RCSID("$NetBSD: hack.do.c,v 1.7 2004/01/27 20:30:29 jsm Exp $");
  64. #endif /* not lint */
  65. /* Contains code for 'd', 'D' (drop), '>', '<' (up, down) and 't' (throw) */
  66. #include "hack.h"
  67. #include "extern.h"
  68. #include <fcntl.h>
  69. #include <unistd.h>
  70. #include <stdlib.h>
  71. static int drop(struct obj *);
  72. int
  73. dodrop()
  74. {
  75. return (drop(getobj("0$#", "drop")));
  76. }
  77. static int
  78. drop(obj)
  79. struct obj *obj;
  80. {
  81. if (!obj)
  82. return (0);
  83. if (obj->olet == '$') { /* pseudo object */
  84. long amount = OGOLD(obj);
  85. if (amount == 0)
  86. pline("You didn't drop any gold pieces.");
  87. else {
  88. mkgold(amount, u.ux, u.uy);
  89. pline("You dropped %ld gold piece%s.",
  90. amount, plur(amount));
  91. if (Invisible)
  92. newsym(u.ux, u.uy);
  93. }
  94. free((char *) obj);
  95. return (1);
  96. }
  97. if (obj->owornmask & (W_ARMOR | W_RING)) {
  98. pline("You cannot drop something you are wearing.");
  99. return (0);
  100. }
  101. if (obj == uwep) {
  102. if (uwep->cursed) {
  103. pline("Your weapon is welded to your hand!");
  104. return (0);
  105. }
  106. setuwep((struct obj *) 0);
  107. }
  108. pline("You dropped %s.", doname(obj));
  109. dropx(obj);
  110. return (1);
  111. }
  112. /* Called in several places - should not produce texts */
  113. void
  114. dropx(obj)
  115. struct obj *obj;
  116. {
  117. freeinv(obj);
  118. dropy(obj);
  119. }
  120. void
  121. dropy(obj)
  122. struct obj *obj;
  123. {
  124. if (obj->otyp == CRYSKNIFE)
  125. obj->otyp = WORM_TOOTH;
  126. obj->ox = u.ux;
  127. obj->oy = u.uy;
  128. obj->nobj = fobj;
  129. fobj = obj;
  130. if (Invisible)
  131. newsym(u.ux, u.uy);
  132. subfrombill(obj);
  133. stackobj(obj);
  134. }
  135. /* drop several things */
  136. int
  137. doddrop()
  138. {
  139. return (ggetobj("drop", drop, 0));
  140. }
  141. int
  142. dodown()
  143. {
  144. if (u.ux != xdnstair || u.uy != ydnstair) {
  145. pline("You can't go down here.");
  146. return (0);
  147. }
  148. if (u.ustuck) {
  149. pline("You are being held, and cannot go down.");
  150. return (1);
  151. }
  152. if (Levitation) {
  153. pline("You're floating high above the stairs.");
  154. return (0);
  155. }
  156. goto_level(dlevel + 1, TRUE);
  157. return (1);
  158. }
  159. int
  160. doup()
  161. {
  162. if (u.ux != xupstair || u.uy != yupstair) {
  163. pline("You can't go up here.");
  164. return (0);
  165. }
  166. if (u.ustuck) {
  167. pline("You are being held, and cannot go up.");
  168. return (1);
  169. }
  170. if (!Levitation && inv_weight() + 5 > 0) {
  171. pline("Your load is too heavy to climb the stairs.");
  172. return (1);
  173. }
  174. goto_level(dlevel - 1, TRUE);
  175. return (1);
  176. }
  177. void
  178. goto_level(newlevel, at_stairs)
  179. int newlevel;
  180. boolean at_stairs;
  181. {
  182. int fd;
  183. boolean up = (newlevel < dlevel);
  184. if (newlevel <= 0)
  185. done("escaped");/* in fact < 0 is impossible */
  186. if (newlevel > MAXLEVEL)
  187. newlevel = MAXLEVEL; /* strange ... */
  188. if (newlevel == dlevel)
  189. return; /* this can happen */
  190. glo(dlevel);
  191. fd = creat(lock, FMASK);
  192. if (fd < 0) {
  193. /*
  194. * This is not quite impossible: e.g., we may have
  195. * exceeded our quota. If that is the case then we
  196. * cannot leave this level, and cannot save either.
  197. * Another possibility is that the directory was not
  198. * writable.
  199. */
  200. pline("A mysterious force prevents you from going %s.",
  201. up ? "up" : "down");
  202. return;
  203. }
  204. if (Punished)
  205. unplacebc();
  206. u.utrap = 0; /* needed in level_tele */
  207. u.ustuck = 0; /* idem */
  208. keepdogs();
  209. seeoff(1);
  210. if (u.uswallow) /* idem */
  211. u.uswldtim = u.uswallow = 0;
  212. flags.nscrinh = 1;
  213. u.ux = FAR; /* hack */
  214. (void) inshop(); /* probably was a trapdoor */
  215. savelev(fd, dlevel);
  216. (void) close(fd);
  217. dlevel = newlevel;
  218. if (maxdlevel < dlevel)
  219. maxdlevel = dlevel;
  220. glo(dlevel);
  221. if (!level_exists[dlevel])
  222. mklev();
  223. else {
  224. if ((fd = open(lock, O_RDONLY)) < 0) {
  225. pline("Cannot open %s .", lock);
  226. pline("Probably someone removed it.");
  227. done("tricked");
  228. }
  229. getlev(fd, hackpid, dlevel);
  230. (void) close(fd);
  231. }
  232. if (at_stairs) {
  233. if (up) {
  234. u.ux = xdnstair;
  235. u.uy = ydnstair;
  236. if (!u.ux) { /* entering a maze from below? */
  237. u.ux = xupstair; /* this will confuse the
  238. * player! */
  239. u.uy = yupstair;
  240. }
  241. if (Punished && !Levitation) {
  242. pline("With great effort you climb the stairs.");
  243. placebc(1);
  244. }
  245. } else {
  246. u.ux = xupstair;
  247. u.uy = yupstair;
  248. if (inv_weight() + 5 > 0 || Punished) {
  249. pline("You fall down the stairs."); /* %% */
  250. losehp(rnd(3), "fall");
  251. if (Punished) {
  252. if (uwep != uball && rn2(3)) {
  253. pline("... and are hit by the iron ball.");
  254. losehp(rnd(20), "iron ball");
  255. }
  256. placebc(1);
  257. }
  258. selftouch("Falling, you");
  259. }
  260. }
  261. {
  262. struct monst *mtmp = m_at(u.ux, u.uy);
  263. if (mtmp)
  264. mnexto(mtmp);
  265. }
  266. } else { /* trapdoor or level_tele */
  267. do {
  268. u.ux = rnd(COLNO - 1);
  269. u.uy = rn2(ROWNO);
  270. } while (levl[u.ux][u.uy].typ != ROOM ||
  271. m_at(u.ux, u.uy));
  272. if (Punished) {
  273. if (uwep != uball && !up /* %% */ && rn2(5)) {
  274. pline("The iron ball falls on your head.");
  275. losehp(rnd(25), "iron ball");
  276. }
  277. placebc(1);
  278. }
  279. selftouch("Falling, you");
  280. }
  281. (void) inshop();
  282. initrack();
  283. losedogs();
  284. {
  285. struct monst *mtmp;
  286. if ((mtmp = m_at(u.ux, u.uy)) != NULL)
  287. mnexto(mtmp); /* riv05!a3 */
  288. }
  289. flags.nscrinh = 0;
  290. setsee();
  291. seeobjs(); /* make old cadavers disappear - riv05!a3 */
  292. docrt();
  293. pickup(1);
  294. read_engr_at(u.ux, u.uy);
  295. }
  296. int
  297. donull()
  298. {
  299. return (1); /* Do nothing, but let other things happen */
  300. }
  301. int
  302. dopray()
  303. {
  304. nomovemsg = "You finished your prayer.";
  305. nomul(-3);
  306. return (1);
  307. }
  308. int
  309. dothrow()
  310. {
  311. struct obj *obj;
  312. struct monst *mon;
  313. int tmp;
  314. obj = getobj("#)", "throw"); /* it is also possible to throw food */
  315. /* (or jewels, or iron balls ... ) */
  316. if (!obj || !getdir(1)) /* ask "in what direction?" */
  317. return (0);
  318. if (obj->owornmask & (W_ARMOR | W_RING)) {
  319. pline("You can't throw something you are wearing.");
  320. return (0);
  321. }
  322. u_wipe_engr(2);
  323. if (obj == uwep) {
  324. if (obj->cursed) {
  325. pline("Your weapon is welded to your hand.");
  326. return (1);
  327. }
  328. if (obj->quan > 1)
  329. setuwep(splitobj(obj, 1));
  330. else
  331. setuwep((struct obj *) 0);
  332. } else if (obj->quan > 1)
  333. (void) splitobj(obj, 1);
  334. freeinv(obj);
  335. if (u.uswallow) {
  336. mon = u.ustuck;
  337. bhitpos.x = mon->mx;
  338. bhitpos.y = mon->my;
  339. } else if (u.dz) {
  340. if (u.dz < 0) {
  341. pline("%s hits the ceiling, then falls back on top of your head.",
  342. Doname(obj)); /* note: obj->quan == 1 */
  343. if (obj->olet == POTION_SYM)
  344. potionhit(&youmonst, obj);
  345. else {
  346. if (uarmh)
  347. pline("Fortunately, you are wearing a helmet!");
  348. losehp(uarmh ? 1 : rnd((int) (obj->owt)), "falling object");
  349. dropy(obj);
  350. }
  351. } else {
  352. pline("%s hits the floor.", Doname(obj));
  353. if (obj->otyp == EXPENSIVE_CAMERA) {
  354. pline("It is shattered in a thousand pieces!");
  355. obfree(obj, Null(obj));
  356. } else if (obj->otyp == EGG) {
  357. pline("\"Splash!\"");
  358. obfree(obj, Null(obj));
  359. } else if (obj->olet == POTION_SYM) {
  360. pline("The flask breaks, and you smell a peculiar odor ...");
  361. potionbreathe(obj);
  362. obfree(obj, Null(obj));
  363. } else {
  364. dropy(obj);
  365. }
  366. }
  367. return (1);
  368. } else if (obj->otyp == BOOMERANG) {
  369. mon = boomhit(u.dx, u.dy);
  370. if (mon == &youmonst) { /* the thing was caught */
  371. (void) addinv(obj);
  372. return (1);
  373. }
  374. } else {
  375. if (obj->otyp == PICK_AXE && shkcatch(obj))
  376. return (1);
  377. mon = bhit(u.dx, u.dy, (obj->otyp == ICE_BOX) ? 1 :
  378. (!Punished || obj != uball) ? 8 : !u.ustuck ? 5 : 1,
  379. obj->olet,
  380. (void (*)(struct monst *, struct obj *)) 0,
  381. (int (*)(struct obj *, struct obj *)) 0, obj);
  382. }
  383. if (mon) {
  384. /* awake monster if sleeping */
  385. wakeup(mon);
  386. if (obj->olet == WEAPON_SYM) {
  387. tmp = -1 + u.ulevel + mon->data->ac + abon();
  388. if (obj->otyp < ROCK) {
  389. if (!uwep ||
  390. uwep->otyp != obj->otyp + (BOW - ARROW))
  391. tmp -= 4;
  392. else {
  393. tmp += uwep->spe;
  394. }
  395. } else if (obj->otyp == BOOMERANG)
  396. tmp += 4;
  397. tmp += obj->spe;
  398. if (u.uswallow || tmp >= rnd(20)) {
  399. if (hmon(mon, obj, 1) == TRUE) {
  400. /* mon still alive */
  401. #ifndef NOWORM
  402. cutworm(mon, bhitpos.x, bhitpos.y, obj->otyp);
  403. #endif /* NOWORM */
  404. } else
  405. mon = 0;
  406. /* weapons thrown disappear sometimes */
  407. if (obj->otyp < BOOMERANG && rn2(3)) {
  408. /* check bill; free */
  409. obfree(obj, (struct obj *) 0);
  410. return (1);
  411. }
  412. } else
  413. miss(objects[obj->otyp].oc_name, mon);
  414. } else if (obj->otyp == HEAVY_IRON_BALL) {
  415. tmp = -1 + u.ulevel + mon->data->ac + abon();
  416. if (!Punished || obj != uball)
  417. tmp += 2;
  418. if (u.utrap)
  419. tmp -= 2;
  420. if (u.uswallow || tmp >= rnd(20)) {
  421. if (hmon(mon, obj, 1) == FALSE)
  422. mon = 0; /* he died */
  423. } else
  424. miss("iron ball", mon);
  425. } else if (obj->olet == POTION_SYM && u.ulevel > rn2(15)) {
  426. potionhit(mon, obj);
  427. return (1);
  428. } else {
  429. if (cansee(bhitpos.x, bhitpos.y))
  430. pline("You miss %s.", monnam(mon));
  431. else
  432. pline("You miss it.");
  433. if (obj->olet == FOOD_SYM && mon->data->mlet == 'd')
  434. if (tamedog(mon, obj))
  435. return (1);
  436. if (obj->olet == GEM_SYM && mon->data->mlet == 'u' &&
  437. !mon->mtame) {
  438. if (obj->dknown && objects[obj->otyp].oc_name_known) {
  439. if (objects[obj->otyp].g_val > 0) {
  440. u.uluck += 5;
  441. goto valuable;
  442. } else {
  443. pline("%s is not interested in your junk.",
  444. Monnam(mon));
  445. }
  446. } else { /* value unknown to @ */
  447. u.uluck++;
  448. valuable:
  449. if (u.uluck > LUCKMAX) /* dan@ut-ngp */
  450. u.uluck = LUCKMAX;
  451. pline("%s graciously accepts your gift.",
  452. Monnam(mon));
  453. mpickobj(mon, obj);
  454. rloc(mon);
  455. return (1);
  456. }
  457. }
  458. }
  459. }
  460. /* the code following might become part of dropy() */
  461. if (obj->otyp == CRYSKNIFE)
  462. obj->otyp = WORM_TOOTH;
  463. obj->ox = bhitpos.x;
  464. obj->oy = bhitpos.y;
  465. obj->nobj = fobj;
  466. fobj = obj;
  467. /* prevent him from throwing articles to the exit and escaping */
  468. /* subfrombill(obj); */
  469. stackobj(obj);
  470. if (Punished && obj == uball &&
  471. (bhitpos.x != u.ux || bhitpos.y != u.uy)) {
  472. freeobj(uchain);
  473. unpobj(uchain);
  474. if (u.utrap) {
  475. if (u.utraptype == TT_PIT)
  476. pline("The ball pulls you out of the pit!");
  477. else {
  478. long side =
  479. rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
  480. pline("The ball pulls you out of the bear trap.");
  481. pline("Your %s leg is severely damaged.",
  482. (side == LEFT_SIDE) ? "left" : "right");
  483. set_wounded_legs(side, 500 + rn2(1000));
  484. losehp(2, "thrown ball");
  485. }
  486. u.utrap = 0;
  487. }
  488. unsee();
  489. uchain->nobj = fobj;
  490. fobj = uchain;
  491. u.ux = uchain->ox = bhitpos.x - u.dx;
  492. u.uy = uchain->oy = bhitpos.y - u.dy;
  493. setsee();
  494. (void) inshop();
  495. }
  496. if (cansee(bhitpos.x, bhitpos.y))
  497. prl(bhitpos.x, bhitpos.y);
  498. return (1);
  499. }
  500. /* split obj so that it gets size num */
  501. /* remainder is put in the object structure delivered by this call */
  502. struct obj *
  503. splitobj(obj, num)
  504. struct obj *obj;
  505. int num;
  506. {
  507. struct obj *otmp;
  508. otmp = newobj(0);
  509. *otmp = *obj; /* copies whole structure */
  510. otmp->o_id = flags.ident++;
  511. otmp->onamelth = 0;
  512. obj->quan = num;
  513. obj->owt = weight(obj);
  514. otmp->quan -= num;
  515. otmp->owt = weight(otmp); /* -= obj->owt ? */
  516. obj->nobj = otmp;
  517. if (obj->unpaid)
  518. splitbill(obj, otmp);
  519. return (otmp);
  520. }
  521. void
  522. more_experienced(exp, rexp)
  523. int exp, rexp;
  524. {
  525. u.uexp += exp;
  526. u.urexp += 4 * exp + rexp;
  527. if (exp)
  528. flags.botl = 1;
  529. if (u.urexp >= ((pl_character[0] == 'W') ? 1000 : 2000))
  530. flags.beginner = 0;
  531. }
  532. void
  533. set_wounded_legs(side, timex)
  534. long side;
  535. int timex;
  536. {
  537. if (!Wounded_legs || (Wounded_legs & TIMEOUT))
  538. Wounded_legs |= side + timex;
  539. else
  540. Wounded_legs |= side;
  541. }
  542. void
  543. heal_legs()
  544. {
  545. if (Wounded_legs) {
  546. if ((Wounded_legs & BOTH_SIDES) == BOTH_SIDES)
  547. pline("Your legs feel somewhat better.");
  548. else
  549. pline("Your leg feels somewhat better.");
  550. Wounded_legs = 0;
  551. }
  552. }