abstract
| - Below is the full text to hack.do.c from the source code of Hack 1.0. To link to a particular line, write [[Hack 1.0/hack.do.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ 2. 3. #include 4. #include 5. #include "hack.h" 6. #include "def.func_tab.h" 7. 8. extern char *getenv(),*parse(),*getlogin(),*lowc(),*unctrl(); 9. extern int float_down(); 10. extern char *nomovemsg, *catmore; 11. extern struct obj *splitobj(), *addinv(); 12. extern boolean hmon(); 13. 14. /* Routines to do various user commands */ 15. 16. int done1(); 17. 18. dodrink() { 19. register struct obj *otmp,*objs; 20. register struct monst *mtmp; 21. register int unkn = 0, nothing = 0; 22. 23. otmp = getobj("!", "drink"); 24. if(!otmp) return(0); 25. switch(otmp->otyp){ 26. case POT_RESTORE_STRENGTH: 27. unkn++; 28. pline("Wow! This makes you feel great!"); 29. if(u.ustr < u.ustrmax) { 30. u.ustr = u.ustrmax; 31. flags.botl = 1; 32. } 33. break; 34. case POT_BOOZE: 35. unkn++; 36. pline("Ooph! This tastes like liquid fire!"); 37. Confusion += d(3,8); 38. /* the whiskey makes us feel better */ 39. if(u.uhp < u.uhpmax) losehp(-1, "bottle of whiskey"); 40. if(!rn2(4)) { 41. pline("You pass out."); 42. multi = -rnd(15); 43. nomovemsg = "You awake with a headache."; 44. } 45. break; 46. case POT_INVISIBILITY: 47. if(Invis) 48. nothing++; 49. else { 50. if(!Blind) 51. pline("Gee! All of a sudden, you can't see yourself."); 52. else 53. pline("You feel rather airy."), unkn++; 54. newsym(u.ux,u.uy); 55. } 56. Invis += rn1(15,31); 57. break; 58. case POT_FRUIT_JUICE: 59. pline("This tastes like fruit juice."); 60. lesshungry(20); 61. break; 62. case POT_HEALING: 63. pline("You begin to feel better."); 64. flags.botl = 1; 65. u.uhp += rnd(10); 66. if(u.uhp > u.uhpmax) 67. u.uhp = ++u.uhpmax; 68. if(Blind) Blind = 1; /* see on next move */ 69. if(Sick) Sick = 0; 70. break; 71. case POT_PARALYSIS: 72. pline("Your feet are frozen to the floor!"); 73. nomul(-(rn1(10,25))); 74. break; 75. case POT_MONSTER_DETECTION: 76. if(!fmon) { 77. strange_feeling(otmp); 78. return(1); 79. } else { 80. cls(); 81. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 82. if(mtmp->mx > 0) 83. at(mtmp->mx,mtmp->my,mtmp->data->mlet); 84. prme(); 85. pline("You sense the presence of monsters."); 86. more(); 87. docrt(); 88. } 89. break; 90. case POT_OBJECT_DETECTION: 91. if(!fobj) { 92. strange_feeling(otmp); 93. return(1); 94. } else { 95. for(objs = fobj; objs; objs = objs->nobj) 96. if(objs->ox != u.ux || objs->oy != u.uy) 97. goto outobjmap; 98. pline("You sense the presence of objects close nearby."); 99. break; 100. outobjmap: 101. cls(); 102. for(objs = fobj; objs; objs = objs->nobj) 103. at(objs->ox,objs->oy,objs->olet); 104. prme(); 105. pline("You sense the presence of objects."); 106. more(); 107. docrt(); 108. } 109. break; 110. case POT_SICKNESS: 111. pline("Yech! This stuff tastes like poison."); 112. if(Poison_resistance) 113. pline("(But in fact it was biologically contaminated orange juice.)"); 114. losestr(rn1(4,3)); 115. losehp(rnd(10), "poison potion"); 116. break; 117. case POT_CONFUSION: 118. if(!Confusion) 119. pline("Huh, What? Where am I?"); 120. else 121. nothing++; 122. Confusion += rn1(7,16); 123. break; 124. case POT_GAIN_STRENGTH: 125. pline("Wow do you feel strong!"); 126. if(u.ustr == 118) break; 127. if(u.ustr > 17) u.ustr += rnd(118-u.ustr); 128. else u.ustr++; 129. if(u.ustr > u.ustrmax) u.ustrmax = u.ustr; 130. flags.botl = 1; 131. break; 132. case POT_SPEED: 133. if(Wounded_legs) { 134. if((Wounded_legs & BOTH_SIDES) == BOTH_SIDES) 135. pline("Your legs feel somewhat better."); 136. else 137. pline("Your leg feels somewhat better."); 138. Wounded_legs = 0; 139. unkn++; 140. break; 141. } 142. if(!(Fast & ~INTRINSIC)) 143. pline("You are suddenly moving much faster."); 144. else 145. pline("Your legs get new energy."), unkn++; 146. Fast += rn1(10,100); 147. break; 148. case POT_BLINDNESS: 149. if(!Blind) 150. pline("A cloud of darkness falls upon you."); 151. else 152. nothing++; 153. Blind += rn1(100,250); 154. seeoff(0); 155. break; 156. case POT_GAIN_LEVEL: 157. pluslvl(); 158. break; 159. case POT_EXTRA_HEALING: 160. pline("You feel much better."); 161. flags.botl = 1; 162. u.uhp += d(2,20)+1; 163. if(u.uhp > u.uhpmax) 164. u.uhp = (u.uhpmax += 2); 165. if(Blind) Blind = 1; 166. if(Sick) Sick = 0; 167. break; 168. case POT_LEVITATION: 169. if(!Levitation) 170. float_up(); 171. else 172. nothing++; 173. Levitation += rnd(100); 174. u.uprops[PROP(RIN_LEVITATION)].p_tofn = float_down; 175. break; 176. default: 177. pline("What a funny potion! (%d)", otmp->otyp); 178. impossible(); 179. return(0); 180. } 181. if(nothing) { 182. unkn++; 183. pline("You have a peculiar feeling for a moment, then it passes."); 184. } 185. if(otmp->dknown && !objects[otmp->otyp].oc_name_known) { 186. if(!unkn) { 187. objects[otmp->otyp].oc_name_known = 1; 188. u.urexp += 10; 189. } else if(!objects[otmp->otyp].oc_uname) 190. docall(otmp); 191. } 192. useup(otmp); 193. return(1); 194. } 195. 196. pluslvl() 197. { 198. register num; 199. 200. pline("You feel more experienced."); 201. num = rnd(10); 202. u.uhpmax += num; 203. u.uhp += num; 204. u.uexp = (10*pow(u.ulevel-1))+1; 205. pline("Welcome to level %d.", ++u.ulevel); 206. flags.botl = 1; 207. } 208. 209. strange_feeling(obj) 210. register struct obj *obj; 211. { 212. pline("You have a strange feeling for a moment, then it passes."); 213. if(!objects[obj->otyp].oc_name_known && !objects[obj->otyp].oc_uname) 214. docall(obj); 215. useup(obj); 216. } 217. 218. dodrop() { 219. register struct obj *obj; 220. 221. obj = getobj("0$#", "drop"); 222. if(!obj) return(0); 223. if(obj->olet == '$') { 224. if(obj->quan == 0) 225. pline("You didn't drop any gold pieces."); 226. else { 227. mkgold((int) obj->quan, u.ux, u.uy); 228. pline("You dropped %u gold piece%s.", 229. obj->quan, plur(obj->quan)); 230. if(Invis) newsym(u.ux, u.uy); 231. } 232. free((char *) obj); 233. return(1); 234. } 235. return(drop(obj)); 236. } 237. 238. drop(obj) register struct obj *obj; { 239. if(obj->owornmask & (W_ARMOR | W_RING)){ 240. pline("You cannot drop something you are wearing."); 241. return(0); 242. } 243. if(obj == uwep) { 244. if(uwep->cursed) { 245. pline("Your weapon is welded to your hand!"); 246. return(0); 247. } 248. setuwep((struct obj *) 0); 249. } 250. pline("You dropped %s.", doname(obj)); 251. dropx(obj); 252. return(1); 253. } 254. 255. dropx(obj) register struct obj *obj; { 256. if(obj->otyp == CRYSKNIFE) 257. obj->otyp = WORM_TOOTH; 258. freeinv(obj); 259. obj->ox = u.ux; 260. obj->oy = u.uy; 261. obj->nobj = fobj; 262. fobj = obj; 263. if(Invis) newsym(u.ux,u.uy); 264. subfrombill(obj); 265. stackobj(obj); 266. } 267. 268. /* drop several things */ 269. doddrop() { 270. return(ggetobj("drop", drop, 0)); 271. } 272. 273. rhack(cmd) 274. register char *cmd; 275. { 276. register struct func_tab *tlist = list; 277. boolean firsttime = FALSE; 278. register res; 279. 280. if(!cmd) { 281. firsttime = TRUE; 282. flags.nopick = 0; 283. cmd = parse(); 284. } 285. if(!*cmd || *cmd == 0377) 286. return; /* probably we just had an interrupt */ 287. if(movecm(cmd)) { 288. walk: 289. if(multi) flags.mv = 1; 290. domove(); 291. return; 292. } 293. if(movecm(lowc(cmd))) { 294. flags.run = 1; 295. rush: 296. if(firsttime){ 297. if(!multi) multi = COLNO; 298. u.last_str_turn = 0; 299. } 300. flags.mv = 1; 301. #ifdef QUEST 302. if(flags.run >= 4) finddir(); 303. if(firsttime){ 304. u.ux0 = u.ux + u.dx; 305. u.uy0 = u.uy + u.dy; 306. } 307. #endif QUEST 308. domove(); 309. return; 310. } 311. if((*cmd == 'f' && movecm(cmd+1)) || 312. movecm(unctrl(cmd))) { 313. flags.run = 2; 314. goto rush; 315. } 316. if(*cmd == 'F' && movecm(lowc(cmd+1))) { 317. flags.run = 3; 318. goto rush; 319. } 320. if(*cmd == 'm' && movecm(cmd+1)) { 321. flags.run = 0; 322. flags.nopick = 1; 323. goto walk; 324. } 325. if(*cmd == 'M' && movecm(lowc(cmd+1))) { 326. flags.run = 1; 327. flags.nopick = 1; 328. goto rush; 329. } 330. #ifdef QUEST 331. if(*cmd == cmd[1] && (*cmd == 'f' || *cmd == 'F')) { 332. flags.run = 4; 333. if(*cmd == 'F') flags.run += 2; 334. if(cmd[2] == '-') flags.run += 1; 335. goto rush; 336. } 337. #endif QUEST 338. while(tlist->f_char) { 339. if(*cmd == tlist->f_char){ 340. res = (*(tlist->f_funct))(0); 341. if(!res) { 342. flags.move = 0; 343. multi = 0; 344. } 345. return; 346. } 347. tlist++; 348. } 349. pline("Unknown command '%s'",cmd); 350. multi = flags.move = 0; 351. } 352. 353. doredraw() 354. { 355. docrt(); 356. return(0); 357. } 358. 359. dohelp() 360. { 361. if(child(1)){ 362. execl(catmore,"more","help",(char *)0); 363. exit(1); 364. } 365. return(0); 366. } 367. 368. #ifdef SHELL 369. dosh(){ 370. register char *str; 371. if(child(0)) { 372. (void) chdir(getenv("HOME")); 373. if(str = getenv("SHELL")) execl(str,str,(char *) 0); 374. if(strcmp("player", getlogin())) 375. execl("/bin/sh","sh",(char *) 0); 376. pline("sh: cannot execute."); 377. exit(1); 378. } 379. return(0); 380. } 381. #endif SHELL 382. 383. #ifdef BSD 384. #include 385. #else 386. #include 387. #endif BSD 388. 389. child(wt) { 390. register int f = fork(); 391. if(f == 0){ /* child */ 392. settty((char *) 0); 393. (void) setuid(getuid()); 394. return(1); 395. } 396. if(f == -1) { /* cannot fork */ 397. pline("Fork failed. Try again."); 398. return(0); 399. } 400. /* fork succeeded; wait for child to exit */ 401. (void) signal(SIGINT,SIG_IGN); 402. (void) signal(SIGQUIT,SIG_IGN); 403. (void) wait((union wait *) 0); 404. setctty(); 405. (void) signal(SIGINT,done1); 406. #ifdef WIZARD 407. if(wizard) (void) signal(SIGQUIT,SIG_DFL); 408. #endif WIZARD 409. if(wt) getret(); 410. docrt(); 411. return(0); 412. } 413. 414. dodown() 415. { 416. if(u.ux != xdnstair || u.uy != ydnstair) { 417. pline("You can't go down here."); 418. return(0); 419. } 420. if(u.ustuck) { 421. pline("You are being held, and cannot go down."); 422. return(1); 423. } 424. if(Levitation) { 425. pline("You're floating high above the stairs."); 426. return(0); 427. } 428. 429. goto_level(dlevel+1, TRUE); 430. return(1); 431. } 432. 433. doup() 434. { 435. if(u.ux != xupstair || u.uy != yupstair) { 436. pline("You can't go up here."); 437. return(0); 438. } 439. if(u.ustuck) { 440. pline("You are being held, and cannot go up."); 441. return(1); 442. } 443. if(inv_weight() + 5 > 0) { 444. pline("Your load is too heavy to climb the stairs."); 445. return(1); 446. } 447. 448. goto_level(dlevel-1, TRUE); 449. return(1); 450. } 451. 452. goto_level(newlevel, at_stairs) 453. register int newlevel; 454. register boolean at_stairs; 455. { 456. register fd; 457. register boolean up = (newlevel < dlevel); 458. 459. if(newlevel <= 0) done("escaped"); /* in fact < 0 is impossible */ 460. if(newlevel == dlevel) return; /* this cannot happen either */ 461. 462. glo(dlevel); 463. fd = creat(lock,FMASK); 464. if(fd < 0) { 465. /* 466. * This is not quite impossible: e.g., we may have 467. * exceeded our quota. If that is the case then we 468. * cannot leave this level, and cannot save either. 469. */ 470. pline("A mysterious force prevents you from going %d.", 471. up ? "up" : "down"); 472. return; 473. } 474. 475. if(Punished) unplacebc(); 476. keepdogs(); 477. seeoff(1); 478. flags.nscrinh = 1; 479. u.ux = FAR; /* hack */ 480. (void) inshop(); /* probably was a trapdoor */ 481. 482. savelev(fd); 483. (void) close(fd); 484. 485. dlevel = newlevel; 486. if(maxdlevel < dlevel) 487. maxdlevel = dlevel; 488. glo(dlevel); 489. if((fd = open(lock,0)) < 0) 490. mklev(); 491. else { 492. (void) getlev(fd); 493. (void) close(fd); 494. } 495. 496. if(at_stairs) { 497. if(up) { 498. u.ux = xdnstair; 499. u.uy = ydnstair; 500. if(!u.ux) { /* entering a maze from below? */ 501. u.ux = xupstair; /* this will confuse the player! */ 502. u.uy = yupstair; 503. } 504. if(Punished){ 505. pline("With great effort you climb the stairs"); 506. placebc(1); 507. } 508. } else { 509. u.ux = xupstair; 510. u.uy = yupstair; 511. if(inv_weight() + 5 > 0 || Punished){ 512. pline("You fall down the stairs."); 513. losehp(rnd(3), "fall"); 514. if(Punished) { 515. if(uwep != uball && rn2(3)){ 516. pline("... and are hit by the iron ball"); 517. losehp(rnd(20), "iron ball"); 518. } 519. placebc(1); 520. } 521. selftouch("Falling, you"); 522. } 523. } 524. } else { /* trapdoor or level_tele */ 525. do { 526. u.ux = rnd(COLNO-1); 527. u.uy = rn2(ROWNO); 528. } while(levl[u.ux][u.uy].typ != ROOM || 529. m_at(u.ux,u.uy)); 530. if(Punished){ 531. if(uwep != uball && !up /* %% */ && rn2(5)){ 532. pline("The iron ball falls on your head."); 533. losehp(rnd(25), "iron ball"); 534. } 535. placebc(1); 536. } 537. selftouch("Falling, you"); 538. } 539. (void) inshop(); 540. #ifdef TRACK 541. initrack(); 542. #endif TRACK 543. 544. losedogs(); 545. flags.nscrinh = 0; 546. setsee(); 547. docrt(); 548. pickup(); 549. read_engr_at(u.ux,u.uy); 550. } 551. 552. donull() { 553. return(1); /* Do nothing, but let other things happen */ 554. } 555. 556. struct monst *bhit(), *boomhit(); 557. dothrow() 558. { 559. register struct obj *obj; 560. register struct monst *mon; 561. register tmp; 562. 563. obj = getobj("#)", "throw"); /* it is also possible to throw food */ 564. /* (or jewels, or iron balls ... ) */ 565. if(!obj || !getdir()) 566. return(0); 567. if(obj->owornmask & (W_ARMOR | W_RING)){ 568. pline("You can't throw something you are wearing"); 569. return(0); 570. } 571. if(obj == uwep){ 572. if(obj->cursed){ 573. pline("Your weapon is welded to your hand"); 574. return(1); 575. } 576. if(obj->quan > 1) 577. setuwep(splitobj(obj, 1)); 578. else 579. setuwep((struct obj *) 0); 580. } 581. else if(obj->quan > 1) 582. (void) splitobj(obj, 1); 583. freeinv(obj); 584. if(u.uswallow) { 585. mon = u.ustuck; 586. bhitpos.x = mon->mx; 587. bhitpos.y = mon->my; 588. } else if(obj->otyp == BOOMERANG) { 589. mon = boomhit(u.dx,u.dy); 590. /* boomhit delivers -1 if the thing was caught */ 591. if((int) mon == -1) { 592. (void) addinv(obj); 593. return(1); 594. } 595. } else 596. mon = bhit(u.dx,u.dy, 597. (!Punished || obj != uball) ? 8 : 598. !u.ustuck ? 5 : 1, 599. obj->olet); 600. if(mon) { 601. /* awake monster if sleeping */ 602. wakeup(mon); 603. 604. if(obj->olet == WEAPON_SYM) { 605. tmp = -1+u.ulevel+mon->data->ac+abon(); 606. if(obj->otyp < ROCK) { 607. if(!uwep || 608. uwep->otyp != obj->otyp+(BOW-ARROW)) 609. tmp -= 4; 610. else { 611. tmp += uwep->spe; 612. } 613. } else 614. if(obj->otyp == BOOMERANG) tmp += 4; 615. tmp += obj->spe; 616. if(u.uswallow || tmp >= rnd(20)) { 617. if(hmon(mon,obj,1) == TRUE){ 618. /* mon still alive */ 619. #ifndef NOWORM 620. cutworm(mon,bhitpos.x,bhitpos.y,obj->otyp); 621. #endif NOWORM 622. } else mon = 0; 623. /* weapons thrown disappear sometimes */ 624. if(obj->otyp < BOOMERANG && rn2(3)) { 625. /* check bill; free */ 626. obfree(obj, (struct obj *) 0); 627. return(1); 628. } 629. } else miss(objects[obj->otyp].oc_name, mon); 630. } else if(obj->otyp == HEAVY_IRON_BALL) { 631. tmp = -1+u.ulevel+mon->data->ac+abon(); 632. if(!Punished || obj != uball) tmp += 2; 633. if(u.utrap) tmp -= 2; 634. if(u.uswallow || tmp >= rnd(20)) { 635. if(hmon(mon,obj,1) == FALSE) 636. mon = 0; /* he died */ 637. } else miss("iron ball", mon); 638. } else { 639. if(cansee(bhitpos.x,bhitpos.y)) 640. pline("You miss %s.",monnam(mon)); 641. else pline("You miss it."); 642. if(obj->olet == FOOD_SYM && mon->data->mlet == 'd') 643. if(tamedog(mon,obj)) return(1); 644. if(obj->olet == GEM_SYM && mon->data->mlet == 'u'){ 645. if(obj->dknown && objects[obj->otyp].oc_name_known){ 646. if(objects[obj->otyp].g_val > 0){ 647. u.uluck += 5; 648. goto valuable; 649. } else { 650. pline("%s is not interested in your junk.", 651. Monnam(mon)); 652. } 653. } else { /* value unknown to @ */ 654. u.uluck++; 655. valuable: 656. pline("%s graciously accepts your gift.", 657. Monnam(mon)); 658. mpickobj(mon, obj); 659. rloc(mon); 660. return(1); 661. } 662. } 663. } 664. } 665. obj->ox = bhitpos.x; 666. obj->oy = bhitpos.y; 667. obj->nobj = fobj; 668. fobj = obj; 669. /* prevent him from throwing articles to the exit and escaping */ 670. /* subfrombill(obj); */ 671. stackobj(obj); 672. if(Punished && obj == uball && 673. (bhitpos.x != u.ux || bhitpos.y != u.uy)){ 674. freeobj(uchain); 675. unpobj(uchain); 676. if(u.utrap){ 677. if(u.utraptype == TT_PIT) 678. pline("The ball pulls you out of the pit!"); 679. else { 680. register int side = 681. rn2(3) ? LEFT_SIDE : RIGHT_SIDE; 682. pline("The ball pulls you out of the bear trap."); 683. pline("Your %s leg is severely damaged.", 684. (side == LEFT_SIDE) ? "left" : "right"); 685. Wounded_legs |= side + rnd(1000); 686. losehp(2, "thrown ball"); 687. } 688. u.utrap = 0; 689. } 690. unsee(); 691. uchain->nobj = fobj; 692. fobj = uchain; 693. u.ux = uchain->ox = bhitpos.x - u.dx; 694. u.uy = uchain->oy = bhitpos.y - u.dy; 695. setsee(); 696. (void) inshop(); 697. } 698. if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y); 699. return(1); 700. } 701. 702. getdir() 703. { 704. char buf[2]; 705. pline("What direction?"); 706. buf[0] = readchar(); 707. buf[1] = 0; 708. return(movecm(buf)); 709. } 710. 711. /* split obj so that it gets size num */ 712. /* remainder is put in the object structure delivered by this call */ 713. struct obj * 714. splitobj(obj, num) register struct obj *obj; register int num; { 715. register struct obj *otmp; 716. otmp = newobj(0); 717. *otmp = *obj; /* copies whole structure */ 718. otmp->o_id = flags.ident++; 719. otmp->onamelth = 0; 720. obj->quan = num; 721. obj->owt = weight(obj); 722. otmp->quan -= num; 723. otmp->owt = weight(otmp); /* -= obj->owt ? */ 724. obj->nobj = otmp; 725. if(obj->unpaid) splitbill(obj,otmp); 726. return(otmp); 727. } 728. 729. char * 730. lowc(str) 731. register char *str; 732. { 733. static char buf[2]; 734. 735. if(*str >= 'A' && *str <= 'Z') *buf = *str+'a'-'A'; 736. else *buf = *str; 737. buf[1] = 0; 738. return(buf); 739. } 740. 741. char * 742. unctrl(str) 743. register char *str; 744. { 745. static char buf[2]; 746. if(*str >= ('A' & 037) && *str <= ('Z' & 037)) 747. *buf = *str + 0140; 748. else *buf = *str; 749. buf[1] = 0; 750. return(buf); 751. }
|