hack.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976
  1. /* $NetBSD: hack.c,v 1.6 2003/04/02 18:36:35 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.c,v 1.6 2003/04/02 18:36:35 jsm Exp $");
  64. #endif /* not lint */
  65. #include "hack.h"
  66. #include "extern.h"
  67. /*
  68. * called on movement: 1. when throwing ball+chain far away 2. when
  69. * teleporting 3. when walking out of a lit room
  70. */
  71. void
  72. unsee()
  73. {
  74. int x, y;
  75. struct rm *lev;
  76. /*
  77. if(u.udispl){
  78. u.udispl = 0;
  79. newsym(u.udisx, u.udisy);
  80. }
  81. */
  82. #ifndef QUEST
  83. if (seehx) {
  84. seehx = 0;
  85. } else
  86. #endif /* QUEST */
  87. for (x = u.ux - 1; x < u.ux + 2; x++)
  88. for (y = u.uy - 1; y < u.uy + 2; y++) {
  89. if (!isok(x, y))
  90. continue;
  91. lev = &levl[x][y];
  92. if (!lev->lit && lev->scrsym == '.') {
  93. lev->scrsym = ' ';
  94. lev->new = 1;
  95. on_scr(x, y);
  96. }
  97. }
  98. }
  99. /*
  100. * called: in hack.eat.c: seeoff(0) - blind after eating rotten food in
  101. * hack.mon.c: seeoff(0) - blinded by a yellow light in hack.mon.c: seeoff(1)
  102. * - swallowed in hack.do.c: seeoff(0) - blind after drinking potion in
  103. * hack.do.c: seeoff(1) - go up or down the stairs in hack.trap.c:seeoff(1)
  104. * - fall through trapdoor
  105. */
  106. void
  107. seeoff(mode)
  108. int mode; /* 1 to redo @, 0 to leave them *//* 1 means
  109. * misc movement, 0 means blindness */
  110. {
  111. int x, y;
  112. struct rm *lev;
  113. if (u.udispl && mode) {
  114. u.udispl = 0;
  115. levl[u.udisx][u.udisy].scrsym = news0(u.udisx, u.udisy);
  116. }
  117. #ifndef QUEST
  118. if (seehx) {
  119. seehx = 0;
  120. } else
  121. #endif /* QUEST */
  122. if (!mode) {
  123. for (x = u.ux - 1; x < u.ux + 2; x++)
  124. for (y = u.uy - 1; y < u.uy + 2; y++) {
  125. if (!isok(x, y))
  126. continue;
  127. lev = &levl[x][y];
  128. if (!lev->lit && lev->scrsym == '.')
  129. lev->seen = 0;
  130. }
  131. }
  132. }
  133. void
  134. domove()
  135. {
  136. xchar oldx, oldy;
  137. struct monst *mtmp = NULL;
  138. struct rm *tmpr, *ust;
  139. struct trap *trap = NULL;
  140. struct obj *otmp = NULL;
  141. u_wipe_engr(rnd(5));
  142. if (inv_weight() > 0) {
  143. pline("You collapse under your load.");
  144. nomul(0);
  145. return;
  146. }
  147. if (u.uswallow) {
  148. u.dx = u.dy = 0;
  149. u.ux = u.ustuck->mx;
  150. u.uy = u.ustuck->my;
  151. } else {
  152. if (Confusion) {
  153. do {
  154. confdir();
  155. } while (!isok(u.ux + u.dx, u.uy + u.dy) ||
  156. IS_ROCK(levl[u.ux + u.dx][u.uy + u.dy].typ));
  157. }
  158. if (!isok(u.ux + u.dx, u.uy + u.dy)) {
  159. nomul(0);
  160. return;
  161. }
  162. }
  163. ust = &levl[u.ux][u.uy];
  164. oldx = u.ux;
  165. oldy = u.uy;
  166. if (!u.uswallow && (trap = t_at(u.ux + u.dx, u.uy + u.dy)) && trap->tseen)
  167. nomul(0);
  168. if (u.ustuck && !u.uswallow && (u.ux + u.dx != u.ustuck->mx ||
  169. u.uy + u.dy != u.ustuck->my)) {
  170. if (dist(u.ustuck->mx, u.ustuck->my) > 2) {
  171. /* perhaps it fled (or was teleported or ... ) */
  172. u.ustuck = 0;
  173. } else {
  174. if (Blind)
  175. pline("You cannot escape from it!");
  176. else
  177. pline("You cannot escape from %s!",
  178. monnam(u.ustuck));
  179. nomul(0);
  180. return;
  181. }
  182. }
  183. if (u.uswallow || (mtmp = m_at(u.ux + u.dx, u.uy + u.dy))) {
  184. /* attack monster */
  185. nomul(0);
  186. gethungry();
  187. if (multi < 0)
  188. return; /* we just fainted */
  189. /* try to attack; note that it might evade */
  190. if (attack(u.uswallow ? u.ustuck : mtmp))
  191. return;
  192. }
  193. /* not attacking an animal, so we try to move */
  194. if (u.utrap) {
  195. if (u.utraptype == TT_PIT) {
  196. pline("You are still in a pit.");
  197. u.utrap--;
  198. } else {
  199. pline("You are caught in a beartrap.");
  200. if ((u.dx && u.dy) || !rn2(5))
  201. u.utrap--;
  202. }
  203. return;
  204. }
  205. tmpr = &levl[u.ux + u.dx][u.uy + u.dy];
  206. if (IS_ROCK(tmpr->typ) ||
  207. (u.dx && u.dy && (tmpr->typ == DOOR || ust->typ == DOOR))) {
  208. flags.move = 0;
  209. nomul(0);
  210. return;
  211. }
  212. while ((otmp = sobj_at(ENORMOUS_ROCK, u.ux + u.dx, u.uy + u.dy)) != NULL){
  213. xchar rx = u.ux + 2 * u.dx, ry = u.uy + 2 * u.dy;
  214. struct trap *ttmp;
  215. nomul(0);
  216. if (isok(rx, ry) && !IS_ROCK(levl[rx][ry].typ) &&
  217. (levl[rx][ry].typ != DOOR || !(u.dx && u.dy)) &&
  218. !sobj_at(ENORMOUS_ROCK, rx, ry)) {
  219. if (m_at(rx, ry)) {
  220. pline("You hear a monster behind the rock.");
  221. pline("Perhaps that's why you cannot move it.");
  222. goto cannot_push;
  223. }
  224. if ((ttmp = t_at(rx, ry)) != NULL)
  225. switch (ttmp->ttyp) {
  226. case PIT:
  227. pline("You push the rock into a pit!");
  228. deltrap(ttmp);
  229. delobj(otmp);
  230. pline("It completely fills the pit!");
  231. continue;
  232. case TELEP_TRAP:
  233. pline("You push the rock and suddenly it disappears!");
  234. delobj(otmp);
  235. continue;
  236. }
  237. if (levl[rx][ry].typ == POOL) {
  238. levl[rx][ry].typ = ROOM;
  239. mnewsym(rx, ry);
  240. prl(rx, ry);
  241. pline("You push the rock into the water.");
  242. pline("Now you can cross the water!");
  243. delobj(otmp);
  244. continue;
  245. }
  246. otmp->ox = rx;
  247. otmp->oy = ry;
  248. /* pobj(otmp); */
  249. if (cansee(rx, ry))
  250. atl(rx, ry, otmp->olet);
  251. if (Invisible)
  252. newsym(u.ux + u.dx, u.uy + u.dy);
  253. {
  254. static long lastmovetime;
  255. /*
  256. * note: this var contains garbage initially
  257. * and after a restore
  258. */
  259. if (moves > lastmovetime + 2 || moves < lastmovetime)
  260. pline("With great effort you move the enormous rock.");
  261. lastmovetime = moves;
  262. }
  263. } else {
  264. pline("You try to move the enormous rock, but in vain.");
  265. cannot_push:
  266. if ((!invent || inv_weight() + 90 <= 0) &&
  267. (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][u.uy + u.dy].typ)
  268. && IS_ROCK(levl[u.ux + u.dx][u.uy].typ)))) {
  269. pline("However, you can squeeze yourself into a small opening.");
  270. break;
  271. } else
  272. return;
  273. }
  274. }
  275. if (u.dx && u.dy && IS_ROCK(levl[u.ux][u.uy + u.dy].typ) &&
  276. IS_ROCK(levl[u.ux + u.dx][u.uy].typ) &&
  277. invent && inv_weight() + 40 > 0) {
  278. pline("You are carrying too much to get through.");
  279. nomul(0);
  280. return;
  281. }
  282. if (Punished &&
  283. DIST(u.ux + u.dx, u.uy + u.dy, uchain->ox, uchain->oy) > 2) {
  284. if (carried(uball)) {
  285. movobj(uchain, u.ux, u.uy);
  286. goto nodrag;
  287. }
  288. if (DIST(u.ux + u.dx, u.uy + u.dy, uball->ox, uball->oy) < 3) {
  289. /* leave ball, move chain under/over ball */
  290. movobj(uchain, uball->ox, uball->oy);
  291. goto nodrag;
  292. }
  293. if (inv_weight() + (int) uball->owt / 2 > 0) {
  294. pline("You cannot %sdrag the heavy iron ball.",
  295. invent ? "carry all that and also " : "");
  296. nomul(0);
  297. return;
  298. }
  299. movobj(uball, uchain->ox, uchain->oy);
  300. unpobj(uball); /* BAH %% */
  301. uchain->ox = u.ux;
  302. uchain->oy = u.uy;
  303. nomul(-2);
  304. nomovemsg = "";
  305. nodrag: ;
  306. }
  307. u.ux += u.dx;
  308. u.uy += u.dy;
  309. if (flags.run) {
  310. if (tmpr->typ == DOOR ||
  311. (xupstair == u.ux && yupstair == u.uy) ||
  312. (xdnstair == u.ux && ydnstair == u.uy))
  313. nomul(0);
  314. }
  315. if (tmpr->typ == POOL && !Levitation)
  316. drown(); /* not necessarily fatal */
  317. /*
  318. if(u.udispl) {
  319. u.udispl = 0;
  320. newsym(oldx,oldy);
  321. }
  322. */
  323. if (!Blind) {
  324. #ifdef QUEST
  325. setsee();
  326. #else
  327. if (ust->lit) {
  328. if (tmpr->lit) {
  329. if (tmpr->typ == DOOR)
  330. prl1(u.ux + u.dx, u.uy + u.dy);
  331. else if (ust->typ == DOOR)
  332. nose1(oldx - u.dx, oldy - u.dy);
  333. } else {
  334. unsee();
  335. prl1(u.ux + u.dx, u.uy + u.dy);
  336. }
  337. } else {
  338. if (tmpr->lit)
  339. setsee();
  340. else {
  341. prl1(u.ux + u.dx, u.uy + u.dy);
  342. if (tmpr->typ == DOOR) {
  343. if (u.dy) {
  344. prl(u.ux - 1, u.uy);
  345. prl(u.ux + 1, u.uy);
  346. } else {
  347. prl(u.ux, u.uy - 1);
  348. prl(u.ux, u.uy + 1);
  349. }
  350. }
  351. }
  352. nose1(oldx - u.dx, oldy - u.dy);
  353. }
  354. #endif /* QUEST */
  355. } else {
  356. pru();
  357. }
  358. if (!flags.nopick)
  359. pickup(1);
  360. if (trap)
  361. dotrap(trap); /* fall into pit, arrow trap, etc. */
  362. (void) inshop();
  363. if (!Blind)
  364. read_engr_at(u.ux, u.uy);
  365. }
  366. void
  367. movobj(obj, ox, oy)
  368. struct obj *obj;
  369. int ox, oy;
  370. {
  371. /* Some dirty programming to get display right */
  372. freeobj(obj);
  373. unpobj(obj);
  374. obj->nobj = fobj;
  375. fobj = obj;
  376. obj->ox = ox;
  377. obj->oy = oy;
  378. }
  379. int
  380. dopickup()
  381. {
  382. if (!g_at(u.ux, u.uy) && !o_at(u.ux, u.uy)) {
  383. pline("There is nothing here to pick up.");
  384. return (0);
  385. }
  386. if (Levitation) {
  387. pline("You cannot reach the floor.");
  388. return (1);
  389. }
  390. pickup(0);
  391. return (1);
  392. }
  393. void
  394. pickup(int all)
  395. {
  396. struct gold *gold;
  397. struct obj *obj, *obj2;
  398. int wt;
  399. if (Levitation)
  400. return;
  401. while ((gold = g_at(u.ux, u.uy)) != NULL) {
  402. pline("%ld gold piece%s.", gold->amount, plur(gold->amount));
  403. u.ugold += gold->amount;
  404. flags.botl = 1;
  405. freegold(gold);
  406. if (flags.run)
  407. nomul(0);
  408. if (Invisible)
  409. newsym(u.ux, u.uy);
  410. }
  411. /* check for more than one object */
  412. if (!all) {
  413. int ct = 0;
  414. for (obj = fobj; obj; obj = obj->nobj)
  415. if (obj->ox == u.ux && obj->oy == u.uy)
  416. if (!Punished || obj != uchain)
  417. ct++;
  418. if (ct < 2)
  419. all++;
  420. else
  421. pline("There are several objects here.");
  422. }
  423. for (obj = fobj; obj; obj = obj2) {
  424. obj2 = obj->nobj; /* perhaps obj will be picked up */
  425. if (obj->ox == u.ux && obj->oy == u.uy) {
  426. if (flags.run)
  427. nomul(0);
  428. /* do not pick up uchain */
  429. if (Punished && obj == uchain)
  430. continue;
  431. if (!all) {
  432. char c;
  433. pline("Pick up %s ? [ynaq]", doname(obj));
  434. while (!strchr("ynaq ", (c = readchar())))
  435. bell();
  436. if (c == 'q')
  437. return;
  438. if (c == 'n')
  439. continue;
  440. if (c == 'a')
  441. all = 1;
  442. }
  443. if (obj->otyp == DEAD_COCKATRICE && !uarmg) {
  444. pline("Touching the dead cockatrice is a fatal mistake.");
  445. pline("You turn to stone.");
  446. killer = "cockatrice cadaver";
  447. done("died");
  448. }
  449. if (obj->otyp == SCR_SCARE_MONSTER) {
  450. if (!obj->spe)
  451. obj->spe = 1;
  452. else {
  453. /*
  454. * Note: perhaps the 1st pickup
  455. * failed: you cannot carry anymore,
  456. * and so we never dropped it - let's
  457. * assume that treading on it twice
  458. * also destroys the scroll
  459. */
  460. pline("The scroll turns to dust as you pick it up.");
  461. delobj(obj);
  462. continue;
  463. }
  464. }
  465. wt = inv_weight() + obj->owt;
  466. if (wt > 0) {
  467. if (obj->quan > 1) {
  468. /* see how many we can lift */
  469. int savequan = obj->quan;
  470. int iw = inv_weight();
  471. int qq;
  472. for (qq = 1; qq < savequan; qq++) {
  473. obj->quan = qq;
  474. if (iw + weight(obj) > 0)
  475. break;
  476. }
  477. obj->quan = savequan;
  478. qq--;
  479. /* we can carry qq of them */
  480. if (!qq)
  481. goto too_heavy;
  482. pline("You can only carry %s of the %s lying here.",
  483. (qq == 1) ? "one" : "some",
  484. doname(obj));
  485. (void) splitobj(obj, qq);
  486. /*
  487. * note: obj2 is set already, so
  488. * we'll never encounter the other
  489. * half; if it should be otherwise
  490. * then write obj2 =
  491. * splitobj(obj,qq);
  492. */
  493. goto lift_some;
  494. }
  495. too_heavy:
  496. pline("There %s %s here, but %s.",
  497. (obj->quan == 1) ? "is" : "are",
  498. doname(obj),
  499. !invent ? "it is too heavy for you to lift"
  500. : "you cannot carry anymore");
  501. break;
  502. }
  503. lift_some:
  504. if (inv_cnt() >= 52) {
  505. pline("Your knapsack cannot accomodate anymore items.");
  506. break;
  507. }
  508. if (wt > -5)
  509. pline("You have a little trouble lifting");
  510. freeobj(obj);
  511. if (Invisible)
  512. newsym(u.ux, u.uy);
  513. addtobill(obj); /* sets obj->unpaid if necessary */
  514. {
  515. int pickquan = obj->quan;
  516. int mergquan;
  517. if (!Blind)
  518. obj->dknown = 1; /* this is done by
  519. * prinv(), but addinv()
  520. * needs it already for
  521. * merging */
  522. obj = addinv(obj); /* might merge it with
  523. * other objects */
  524. mergquan = obj->quan;
  525. obj->quan = pickquan; /* to fool prinv() */
  526. prinv(obj);
  527. obj->quan = mergquan;
  528. }
  529. }
  530. }
  531. }
  532. /* stop running if we see something interesting */
  533. /* turn around a corner if that is the only way we can proceed */
  534. /* do not turn left or right twice */
  535. void
  536. lookaround()
  537. {
  538. int x, y, i, x0 = 0, y0 = 0, m0 = 0, i0 = 9;
  539. int corrct = 0, noturn = 0;
  540. struct monst *mtmp;
  541. if (Blind || flags.run == 0)
  542. return;
  543. if (flags.run == 1 && levl[u.ux][u.uy].typ == ROOM)
  544. return;
  545. #ifdef QUEST
  546. if (u.ux0 == u.ux + u.dx && u.uy0 == u.uy + u.dy)
  547. goto stop;
  548. #endif /* QUEST */
  549. for (x = u.ux - 1; x <= u.ux + 1; x++)
  550. for (y = u.uy - 1; y <= u.uy + 1; y++) {
  551. if (x == u.ux && y == u.uy)
  552. continue;
  553. if (!levl[x][y].typ)
  554. continue;
  555. if ((mtmp = m_at(x, y)) && !mtmp->mimic &&
  556. (!mtmp->minvis || See_invisible)) {
  557. if (!mtmp->mtame || (x == u.ux + u.dx && y == u.uy + u.dy))
  558. goto stop;
  559. } else
  560. mtmp = 0; /* invisible M cannot
  561. * influence us */
  562. if (x == u.ux - u.dx && y == u.uy - u.dy)
  563. continue;
  564. switch (levl[x][y].scrsym) {
  565. case '|':
  566. case '-':
  567. case '.':
  568. case ' ':
  569. break;
  570. case '+':
  571. if (x != u.ux && y != u.uy)
  572. break;
  573. if (flags.run != 1)
  574. goto stop;
  575. /* fall into next case */
  576. case CORR_SYM:
  577. corr:
  578. if (flags.run == 1 || flags.run == 3) {
  579. i = DIST(x, y, u.ux + u.dx, u.uy + u.dy);
  580. if (i > 2)
  581. break;
  582. if (corrct == 1 && DIST(x, y, x0, y0) != 1)
  583. noturn = 1;
  584. if (i < i0) {
  585. i0 = i;
  586. x0 = x;
  587. y0 = y;
  588. m0 = mtmp ? 1 : 0;
  589. }
  590. }
  591. corrct++;
  592. break;
  593. case '^':
  594. if (flags.run == 1)
  595. goto corr; /* if you must */
  596. if (x == u.ux + u.dx && y == u.uy + u.dy)
  597. goto stop;
  598. break;
  599. default: /* e.g. objects or trap or stairs */
  600. if (flags.run == 1)
  601. goto corr;
  602. if (mtmp)
  603. break; /* d */
  604. stop:
  605. nomul(0);
  606. return;
  607. }
  608. }
  609. #ifdef QUEST
  610. if (corrct > 0 && (flags.run == 4 || flags.run == 5))
  611. goto stop;
  612. #endif /* QUEST */
  613. if (corrct > 1 && flags.run == 2)
  614. goto stop;
  615. if ((flags.run == 1 || flags.run == 3) && !noturn && !m0 && i0 &&
  616. (corrct == 1 || (corrct == 2 && i0 == 1))) {
  617. /* make sure that we do not turn too far */
  618. if (i0 == 2) {
  619. if (u.dx == y0 - u.uy && u.dy == u.ux - x0)
  620. i = 2; /* straight turn right */
  621. else
  622. i = -2; /* straight turn left */
  623. } else if (u.dx && u.dy) {
  624. if ((u.dx == u.dy && y0 == u.uy) ||
  625. (u.dx != u.dy && y0 != u.uy))
  626. i = -1; /* half turn left */
  627. else
  628. i = 1; /* half turn right */
  629. } else {
  630. if ((x0 - u.ux == y0 - u.uy && !u.dy) ||
  631. (x0 - u.ux != y0 - u.uy && u.dy))
  632. i = 1; /* half turn right */
  633. else
  634. i = -1; /* half turn left */
  635. }
  636. i += u.last_str_turn;
  637. if (i <= 2 && i >= -2) {
  638. u.last_str_turn = i;
  639. u.dx = x0 - u.ux, u.dy = y0 - u.uy;
  640. }
  641. }
  642. }
  643. /* something like lookaround, but we are not running */
  644. /* react only to monsters that might hit us */
  645. int
  646. monster_nearby()
  647. {
  648. int x, y;
  649. struct monst *mtmp;
  650. if (!Blind)
  651. for (x = u.ux - 1; x <= u.ux + 1; x++)
  652. for (y = u.uy - 1; y <= u.uy + 1; y++) {
  653. if (x == u.ux && y == u.uy)
  654. continue;
  655. if ((mtmp = m_at(x, y)) && !mtmp->mimic && !mtmp->mtame &&
  656. !mtmp->mpeaceful && !strchr("Ea", mtmp->data->mlet) &&
  657. !mtmp->mfroz && !mtmp->msleep && /* aplvax!jcn */
  658. (!mtmp->minvis || See_invisible))
  659. return (1);
  660. }
  661. return (0);
  662. }
  663. #ifdef QUEST
  664. int
  665. cansee(x, y)
  666. xchar x, y;
  667. {
  668. int dx, dy, adx, ady, sdx, sdy, dmax, d;
  669. if (Blind)
  670. return (0);
  671. if (!isok(x, y))
  672. return (0);
  673. d = dist(x, y);
  674. if (d < 3)
  675. return (1);
  676. if (d > u.uhorizon * u.uhorizon)
  677. return (0);
  678. if (!levl[x][y].lit)
  679. return (0);
  680. dx = x - u.ux;
  681. adx = abs(dx);
  682. sdx = sgn(dx);
  683. dy = y - u.uy;
  684. ady = abs(dy);
  685. sdy = sgn(dy);
  686. if (dx == 0 || dy == 0 || adx == ady) {
  687. dmax = (dx == 0) ? ady : adx;
  688. for (d = 1; d <= dmax; d++)
  689. if (!rroom(sdx * d, sdy * d))
  690. return (0);
  691. return (1);
  692. } else if (ady > adx) {
  693. for (d = 1; d <= ady; d++) {
  694. if (!rroom(sdx * ((d * adx) / ady), sdy * d) ||
  695. !rroom(sdx * ((d * adx - 1) / ady + 1), sdy * d))
  696. return (0);
  697. }
  698. return (1);
  699. } else {
  700. for (d = 1; d <= adx; d++) {
  701. if (!rroom(sdx * d, sdy * ((d * ady) / adx)) ||
  702. !rroom(sdx * d, sdy * ((d * ady - 1) / adx + 1)))
  703. return (0);
  704. }
  705. return (1);
  706. }
  707. }
  708. int
  709. rroom(x, y)
  710. int x, y;
  711. {
  712. return (IS_ROOM(levl[u.ux + x][u.uy + y].typ));
  713. }
  714. #else
  715. int
  716. cansee(x, y)
  717. xchar x, y;
  718. {
  719. if (Blind || u.uswallow)
  720. return (0);
  721. if (dist(x, y) < 3)
  722. return (1);
  723. if (levl[x][y].lit && seelx <= x && x <= seehx && seely <= y &&
  724. y <= seehy)
  725. return (1);
  726. return (0);
  727. }
  728. #endif /* QUEST */
  729. int
  730. sgn(a)
  731. int a;
  732. {
  733. return ((a > 0) ? 1 : (a == 0) ? 0 : -1);
  734. }
  735. #ifdef QUEST
  736. void
  737. setsee()
  738. {
  739. int x, y;
  740. if (Blind) {
  741. pru();
  742. return;
  743. }
  744. for (y = u.uy - u.uhorizon; y <= u.uy + u.uhorizon; y++)
  745. for (x = u.ux - u.uhorizon; x <= u.ux + u.uhorizon; x++) {
  746. if (cansee(x, y))
  747. prl(x, y);
  748. }
  749. }
  750. #else
  751. void
  752. setsee()
  753. {
  754. int x, y;
  755. if (Blind) {
  756. pru();
  757. return;
  758. }
  759. if (!levl[u.ux][u.uy].lit) {
  760. seelx = u.ux - 1;
  761. seehx = u.ux + 1;
  762. seely = u.uy - 1;
  763. seehy = u.uy + 1;
  764. } else {
  765. for (seelx = u.ux; levl[seelx - 1][u.uy].lit; seelx--);
  766. for (seehx = u.ux; levl[seehx + 1][u.uy].lit; seehx++);
  767. for (seely = u.uy; levl[u.ux][seely - 1].lit; seely--);
  768. for (seehy = u.uy; levl[u.ux][seehy + 1].lit; seehy++);
  769. }
  770. for (y = seely; y <= seehy; y++)
  771. for (x = seelx; x <= seehx; x++) {
  772. prl(x, y);
  773. }
  774. if (!levl[u.ux][u.uy].lit)
  775. seehx = 0; /* seems necessary elsewhere */
  776. else {
  777. if (seely == u.uy)
  778. for (x = u.ux - 1; x <= u.ux + 1; x++)
  779. prl(x, seely - 1);
  780. if (seehy == u.uy)
  781. for (x = u.ux - 1; x <= u.ux + 1; x++)
  782. prl(x, seehy + 1);
  783. if (seelx == u.ux)
  784. for (y = u.uy - 1; y <= u.uy + 1; y++)
  785. prl(seelx - 1, y);
  786. if (seehx == u.ux)
  787. for (y = u.uy - 1; y <= u.uy + 1; y++)
  788. prl(seehx + 1, y);
  789. }
  790. }
  791. #endif /* QUEST */
  792. void
  793. nomul(nval)
  794. int nval;
  795. {
  796. if (multi < 0)
  797. return;
  798. multi = nval;
  799. flags.mv = flags.run = 0;
  800. }
  801. int
  802. abon()
  803. {
  804. if (u.ustr == 3)
  805. return (-3);
  806. else if (u.ustr < 6)
  807. return (-2);
  808. else if (u.ustr < 8)
  809. return (-1);
  810. else if (u.ustr < 17)
  811. return (0);
  812. else if (u.ustr < 69)
  813. return (1); /* up to 18/50 */
  814. else if (u.ustr < 118)
  815. return (2);
  816. else
  817. return (3);
  818. }
  819. int
  820. dbon()
  821. {
  822. if (u.ustr < 6)
  823. return (-1);
  824. else if (u.ustr < 16)
  825. return (0);
  826. else if (u.ustr < 18)
  827. return (1);
  828. else if (u.ustr == 18)
  829. return (2); /* up to 18 */
  830. else if (u.ustr < 94)
  831. return (3); /* up to 18/75 */
  832. else if (u.ustr < 109)
  833. return (4); /* up to 18/90 */
  834. else if (u.ustr < 118)
  835. return (5); /* up to 18/99 */
  836. else
  837. return (6);
  838. }
  839. void
  840. losestr(num) /* may kill you; cause may be poison or */
  841. int num; /* monster like 'A' */
  842. {
  843. u.ustr -= num;
  844. while (u.ustr < 3) {
  845. u.ustr++;
  846. u.uhp -= 6;
  847. u.uhpmax -= 6;
  848. }
  849. flags.botl = 1;
  850. }
  851. void
  852. losehp(n, knam)
  853. int n;
  854. const char *knam;
  855. {
  856. u.uhp -= n;
  857. if (u.uhp > u.uhpmax)
  858. u.uhpmax = u.uhp; /* perhaps n was negative */
  859. flags.botl = 1;
  860. if (u.uhp < 1) {
  861. killer = knam; /* the thing that killed you */
  862. done("died");
  863. }
  864. }
  865. void
  866. losehp_m(n, mtmp)
  867. int n;
  868. struct monst *mtmp;
  869. {
  870. u.uhp -= n;
  871. flags.botl = 1;
  872. if (u.uhp < 1)
  873. done_in_by(mtmp);
  874. }
  875. void
  876. losexp()
  877. { /* hit by V or W */
  878. int num;
  879. if (u.ulevel > 1)
  880. pline("Goodbye level %u.", u.ulevel--);
  881. else
  882. u.uhp = -1;
  883. num = rnd(10);
  884. u.uhp -= num;
  885. u.uhpmax -= num;
  886. u.uexp = newuexp();
  887. flags.botl = 1;
  888. }
  889. int
  890. inv_weight()
  891. {
  892. struct obj *otmp = invent;
  893. int wt = (u.ugold + 500) / 1000;
  894. int carrcap;
  895. if (Levitation) /* pugh@cornell */
  896. carrcap = MAX_CARR_CAP;
  897. else {
  898. carrcap = 5 * (((u.ustr > 18) ? 20 : u.ustr) + u.ulevel);
  899. if (carrcap > MAX_CARR_CAP)
  900. carrcap = MAX_CARR_CAP;
  901. if (Wounded_legs & LEFT_SIDE)
  902. carrcap -= 10;
  903. if (Wounded_legs & RIGHT_SIDE)
  904. carrcap -= 10;
  905. }
  906. while (otmp) {
  907. wt += otmp->owt;
  908. otmp = otmp->nobj;
  909. }
  910. return (wt - carrcap);
  911. }
  912. int
  913. inv_cnt()
  914. {
  915. struct obj *otmp = invent;
  916. int ct = 0;
  917. while (otmp) {
  918. ct++;
  919. otmp = otmp->nobj;
  920. }
  921. return (ct);
  922. }
  923. long
  924. newuexp()
  925. {
  926. return (10 * (1L << (u.ulevel - 1)));
  927. }