abstract
| - Below is the full text to engrave.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.0/engrave.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)engrave.c 3.3 1999/08/16 */ 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. #include "lev.h" 7. #include 8. 9. STATIC_VAR NEARDATA struct engr *head_engr; 10. 11. #ifdef OVLB 12. /* random engravings */ 13. static const char *random_mesg[] = { 14. "Elbereth", 15. /* trap engravings */ 16. "Vlad was here", "ad aerarium", 17. /* take-offs and other famous engravings */ 18. "Owlbreath", "Galadriel", 19. "Kilroy was here", 20. "A.S. ->", "<- A.S.", /* Journey to the Center of the Earth */ 21. "You won't get it up the steps", /* Adventure */ 22. "Lasciate ogni speranza o voi ch'entrate.", /* Inferno */ 23. "Well Come", /* Prisoner */ 24. "We apologize for the inconvenience.", /* So Long... */ 25. "See you next Wednesday", /* Thriller */ 26. "notary sojak", /* Smokey Stover */ 27. "For a good time call 8?7-5309", 28. "Please don't feed the animals.", /* Various zoos around the world */ 29. "Madam, in Eden, I'm Adam.", /* A palindrome */ 30. "Two thumbs up!", /* Siskel & Ebert */ 31. "Hello, World!", /* The First C Program */ 32. #ifdef MAIL 33. "You've got mail!", /* AOL */ 34. #endif 35. "As if!", /* Clueless */ 36. }; 37. 38. char * 39. random_engraving(outbuf) 40. char *outbuf; 41. { 42. const char *rumor; 43. 44. /* a random engraving may come from the "rumors" file, 45. or from the list above */ 46. if (!rn2(4) || !(rumor = getrumor(0, outbuf)) || !*rumor) 47. Strcpy(outbuf, random_mesg[rn2(SIZE(random_mesg))]); 48. 49. wipeout_text(outbuf, (int)(strlen(outbuf) / 4), 0); 50. return outbuf; 51. } 52. 53. /* Partial rubouts for engraving characters. -3. */ 54. static const struct { 55. char wipefrom; 56. const char * wipeto; 57. } rubouts[] = { 58. {'A', "^"}, {'B', "Pb["}, {'C', "("}, {'D', "|)["}, 59. {'E', "|FL[_"}, {'F', "|-"}, {'G', "C("}, {'H', "|-"}, 60. {'I', "|"}, {'K', "|<"}, {'L', "|_"}, {'M', "|"}, 61. {'N', "|\\"}, {'O', "C("}, {'P', "F"}, {'Q', "C("}, 62. {'R', "PF"}, {'T', "|"}, {'U', "J"}, {'V', "/\\"}, 63. {'W', "V/\\"}, {'Z', "/"}, 64. {'b', "|"}, {'d', "c|"}, {'e', "c"}, {'g', "c"}, 65. {'h', "n"}, {'j', "i"}, {'k', "|"}, {'l', "|"}, 66. {'m', "nr"}, {'n', "r"}, {'o', "c"}, {'q', "c"}, 67. {'w', "v"}, {'y', "v"}, 68. {':', "."}, {';', ","}, 69. {'0', "C("}, {'1', "|"}, {'6', "o"}, {'7', "/"}, 70. {'8', "3o"} 71. }; 72. 73. void 74. wipeout_text(engr, cnt, seed) 75. char *engr; 76. int cnt; 77. unsigned seed; /* for semi-controlled randomization */ 78. { 79. char *s; 80. int i, j, nxt, use_rubout, lth = (int)strlen(engr); 81. 82. if (lth && cnt > 0) { 83. while (cnt--) { 84. /* pick next character */ 85. if (!seed) { 86. /* random */ 87. nxt = rn2(lth); 88. use_rubout = rn2(4); 89. } else { 90. /* predictable; caller can reproduce the same sequence by 91. supplying the same arguments later, or a pseudo-random 92. sequence by varying any of them */ 93. nxt = seed % lth; 94. seed *= 31, seed %= (BUFSZ-1); 95. use_rubout = seed & 3; 96. } 97. s = &engr[nxt]; 98. if (*s == ' ') continue; 99. 100. /* rub out unreadable & small punctuation marks */ 101. if (index("?.,'`-|_", *s)) { 102. *s = ' '; 103. continue; 104. } 105. 106. if (!use_rubout) 107. i = SIZE(rubouts); 108. else 109. for (i = 0; i < SIZE(rubouts); i++) 110. if (*s == rubouts[i].wipefrom) { 111. /* 112. * Pick one of the substitutes at random. 113. */ 114. if (!seed) 115. j = rn2(strlen(rubouts[i].wipeto)); 116. else { 117. seed *= 31, seed %= (BUFSZ-1); 118. j = seed % (strlen(rubouts[i].wipeto)); 119. } 120. *s = rubouts[i].wipeto[j]; 121. break; 122. } 123. 124. /* didn't pick rubout; use '?' for unreadable character */ 125. if (i == SIZE(rubouts)) *s = '?'; 126. } 127. } 128. 129. /* trim trailing spaces */ 130. while (lth && engr[lth-1] == ' ') engr[--lth] = 0; 131. } 132. 133. boolean 134. can_reach_floor() 135. { 136. return (boolean)(!u.uswallow && 137. #ifdef STEED 138. /* Restricted/unskilled riders can't reach the floor */ 139. !(u.usteed && P_SKILL(P_RIDING) < P_BASIC) && 140. #endif 141. (!Levitation || 142. Is_airlevel(&u.uz) || Is_waterlevel(&u.uz))); 143. } 144. #endif /* OVLB */ 145. #ifdef OVL0 146. 147. const char * 148. surface(x, y) 149. register int x, y; 150. { 151. register struct rm *lev = &levl[x][y]; 152. 153. if ((x == u.ux) && (y == u.uy) && u.uswallow && 154. is_animal(u.ustuck->data)) 155. return "maw"; 156. else if (IS_AIR(lev->typ)) 157. return "air"; 158. else if (is_pool(x,y)) 159. return "water"; 160. else if (is_ice(x,y)) 161. return "ice"; 162. else if (is_lava(x,y)) 163. return "lava"; 164. else if (lev->typ == DRAWBRIDGE_DOWN) 165. return "bridge"; 166. else if(IS_ALTAR(levl[x][y].typ)) 167. return "altar"; 168. else if ((IS_ROOM(lev->typ) && !Is_earthlevel(&u.uz)) || 169. IS_WALL(lev->typ) || IS_DOOR(lev->typ) || lev->typ == SDOOR) 170. return "floor"; 171. else 172. return "ground"; 173. } 174. 175. const char * 176. ceiling(x, y) 177. register int x, y; 178. { 179. register struct rm *lev = &levl[x][y]; 180. const char *what; 181. 182. /* other room types will no longer exist when we're interested -- 183. * see check_special_room() 184. */ 185. if (*in_rooms(x,y,VAULT)) 186. what = "vault's ceiling"; 187. else if (*in_rooms(x,y,TEMPLE)) 188. what = "temple's ceiling"; 189. else if (*in_rooms(x,y,SHOPBASE)) 190. what = "shop's ceiling"; 191. else if (IS_AIR(lev->typ)) 192. what = "sky"; 193. else if (Underwater) 194. what = "water's surface"; 195. else if ((IS_ROOM(lev->typ) && !Is_earthlevel(&u.uz)) || 196. IS_WALL(lev->typ) || IS_DOOR(lev->typ) || lev->typ == SDOOR) 197. what = "ceiling"; 198. else 199. what = "rock above"; 200. 201. return what; 202. } 203. 204. struct engr * 205. engr_at(x, y) 206. xchar x, y; 207. { 208. register struct engr *ep = head_engr; 209. 210. while(ep) { 211. if(x == ep->engr_x && y == ep->engr_y) 212. return(ep); 213. ep = ep->nxt_engr; 214. } 215. return((struct engr *) 0); 216. } 217. 218. #ifdef ELBERETH 219. /* decide whether a particular string is engraved at a specified location; 220. a case-insensitive substring match used */ 221. int 222. sengr_at(s, x, y) 223. const char *s; 224. xchar x, y; 225. { 226. register struct engr *ep = engr_at(x,y); 227. 228. return (ep && ep->engr_time <= moves && strstri(ep->engr_txt, s) != 0); 229. } 230. #endif /* ELBERETH */ 231. 232. #endif /* OVL0 */ 233. #ifdef OVL2 234. 235. void 236. u_wipe_engr(cnt) 237. register int cnt; 238. { 239. if (can_reach_floor()) 240. wipe_engr_at(u.ux, u.uy, cnt); 241. } 242. 243. #endif /* OVL2 */ 244. #ifdef OVL1 245. 246. void 247. wipe_engr_at(x,y,cnt) 248. register xchar x,y,cnt; 249. { 250. register struct engr *ep = engr_at(x,y); 251. 252. if(ep){ 253. if(ep->engr_type != BURN || is_ice(x,y)) { 254. if(ep->engr_type != DUST && ep->engr_type != BLOOD) { 255. cnt = rn2(1 + 50/(cnt+1)) ? 0 : 1; 256. } 257. wipeout_text(ep->engr_txt, (int)cnt, 0); 258. while(ep->engr_txt[0] == ' ') 259. ep->engr_txt++; 260. if(!ep->engr_txt[0]) del_engr(ep); 261. } 262. } 263. } 264. 265. #endif /* OVL1 */ 266. #ifdef OVL2 267. 268. void 269. read_engr_at(x,y) 270. register int x,y; 271. { 272. register struct engr *ep = engr_at(x,y); 273. register int sensed = 0; 274. 275. if(ep && ep->engr_txt[0]) { 276. switch(ep->engr_type) { 277. case DUST: 278. if(!Blind) { 279. sensed = 1; 280. pline("%s is written here in the %s.", Something, 281. is_ice(x,y) ? "frost" : "dust"); 282. } 283. break; 284. case ENGRAVE: 285. if (!Blind || can_reach_floor()) { 286. sensed = 1; 287. pline("%s is engraved here on the %s.", 288. Something, 289. surface(x,y)); 290. } 291. break; 292. case BURN: 293. if (!Blind || can_reach_floor()) { 294. sensed = 1; 295. pline("Some text has been %s into the %s here.", 296. is_ice(x,y) ? "melted" : "burned", 297. surface(x,y)); 298. } 299. break; 300. case MARK: 301. if(!Blind) { 302. sensed = 1; 303. pline("There's some graffiti on the %s here.", 304. surface(x,y)); 305. } 306. break; 307. case BLOOD: 308. /* "It's a message! Scrawled in blood!" 309. * "What's it say?" 310. * "It says... `See you next Wednesday.'" -- Thriller 311. */ 312. if(!Blind) { 313. sensed = 1; 314. You("see a message scrawled in blood here."); 315. } 316. break; 317. default: 318. impossible("%s is written in a very strange way.", 319. Something); 320. sensed = 1; 321. } 322. if (sensed) { 323. You("%s: \"%s\".", 324. (Blind) ? "feel the words" : "read", ep->engr_txt); 325. if(flags.run > 1) nomul(0); 326. } 327. } 328. } 329. 330. #endif /* OVL2 */ 331. #ifdef OVLB 332. 333. void 334. make_engr_at(x,y,s,e_time,e_type) 335. register int x,y; 336. register const char *s; 337. register long e_time; 338. register xchar e_type; 339. { 340. register struct engr *ep; 341. 342. if ((ep = engr_at(x,y)) != 0) 343. del_engr(ep); 344. ep = newengr(strlen(s) + 1); 345. ep->nxt_engr = head_engr; 346. head_engr = ep; 347. ep->engr_x = x; 348. ep->engr_y = y; 349. ep->engr_txt = (char *)(ep + 1); 350. Strcpy(ep->engr_txt, s); 351. if(strcmp(s, "Elbereth")) exercise(A_WIS, TRUE); 352. ep->engr_time = e_time; 353. ep->engr_type = e_type > 0 ? e_type : rnd(N_ENGRAVE); 354. ep->engr_lth = strlen(s) + 1; 355. } 356. 357. /* delete any engraving at location */ 358. void 359. del_engr_at(x, y) 360. int x, y; 361. { 362. register struct engr *ep = engr_at(x, y); 363. 364. if (ep) del_engr(ep); 365. } 366. 367. /* 368. * freehand - returns true if player has a free hand 369. */ 370. int 371. freehand() 372. { 373. return(!uwep || !welded(uwep) || 374. (!bimanual(uwep) && (!uarms || !uarms->cursed))); 375. /* if ((uwep && bimanual(uwep)) || 376. (uwep && uarms)) 377. return(0); 378. else 379. return(1);*/ 380. } 381. 382. static NEARDATA const char styluses[] = 383. { ALL_CLASSES, ALLOW_NONE, TOOL_CLASS, WEAPON_CLASS, WAND_CLASS, 384. GEM_CLASS, RING_CLASS, 0 }; 385. 386. /* Mohs' Hardness Scale: 387. * 1 - Talc 6 - Orthoclase 388. * 2 - Gypsum 7 - Quartz 389. * 3 - Calcite 8 - Topaz 390. * 4 - Fluorite 9 - Corundum 391. * 5 - Apatite 10 - Diamond 392. * 393. * Since granite is a igneous rock hardness ~ 7, anything >= 8 should 394. * probably be able to scratch the rock. 395. * Devaluation of less hard gems is not easily possible because obj struct 396. * does not contain individual oc_cost currently. 7/91 397. * 398. * steel - 5-8.5 (usu. weapon) 399. * diamond - 10 * jade - 5-6 (nephrite) 400. * ruby - 9 (corundum) * turquoise - 5-6 401. * sapphire - 9 (corundum) * opal - 5-6 402. * topaz - 8 * glass - ~5.5 403. * emerald - 7.5-8 (beryl) * dilithium - 4-5?? 404. * aquamarine - 7.5-8 (beryl) * iron - 4-5 405. * garnet - 7.25 (var. 6.5-8) * fluorite - 4 406. * agate - 7 (quartz) * brass - 3-4 407. * amethyst - 7 (quartz) * gold - 2.5-3 408. * jasper - 7 (quartz) * silver - 2.5-3 409. * onyx - 7 (quartz) * copper - 2.5-3 410. * moonstone - 6 (orthoclase) * amber - 2-2.5 411. */ 412. 413. /* return 1 if action took 1 (or more) moves, 0 if error or aborted */ 414. int 415. doengrave() 416. { 417. boolean dengr = FALSE; /* TRUE if we wipe out the current engraving */ 418. boolean doblind = FALSE;/* TRUE if engraving blinds the player */ 419. boolean doknown = FALSE;/* TRUE if we identify the stylus */ 420. boolean eow = FALSE; /* TRUE if we are overwriting oep */ 421. boolean jello = FALSE; /* TRUE if we are engraving in slime */ 422. boolean ptext = TRUE; /* TRUE if we must prompt for engrave text */ 423. boolean teleengr =FALSE;/* TRUE if we move the old engraving */ 424. boolean zapwand = FALSE;/* TRUE if we remove a wand charge */ 425. xchar type = DUST; /* Type of engraving made */ 426. char buf[BUFSZ]; /* Buffer for final/poly engraving text */ 427. char ebuf[BUFSZ]; /* Buffer for initial engraving text */ 428. char qbuf[QBUFSZ]; /* Buffer for query text */ 429. char post_engr_text[BUFSZ]; /* Text displayed after engraving prompt */ 430. const char *everb; /* Present tense of engraving type */ 431. const char *eloc; /* Where the engraving is (ie dust/floor/...) */ 432. register char *sp; /* Place holder for space count of engr text */ 433. register int len; /* # of nonspace chars of new engraving text */ 434. register int maxelen; /* Max allowable length of new engraving text */ 435. register int spct; /* # of spaces in new engraving text */ 436. register struct engr *oep = engr_at(u.ux,u.uy); 437. /* The current engraving */ 438. register struct obj *otmp; /* Object selected with which to engrave */ 439. char *writer; 440. 441. 442. multi = 0; /* moves consumed */ 443. nomovemsg = (char *)0; /* occupation end message */ 444. 445. buf[0] = (char)0; 446. ebuf[0] = (char)0; 447. post_engr_text[0] = (char)0; 448. maxelen = BUFSZ - 1; 449. 450. /* Can the adventurer engrave at all? */ 451. 452. if(u.uswallow) { 453. if (is_animal(u.ustuck->data)) { 454. pline("What would you write? \"Jonah was here\"?"); 455. return(0); 456. } else if (is_whirly(u.ustuck->data)) { 457. You_cant("reach the %s.", surface(u.ux,u.uy)); 458. return(0); 459. } else 460. jello = TRUE; 461. } else if (is_lava(u.ux, u.uy)) { 462. You_cant("write on the lava!"); 463. return(0); 464. } else if (is_pool(u.ux,u.uy) || IS_FOUNTAIN(levl[u.ux][u.uy].typ)) { 465. You_cant("write on the water!"); 466. return(0); 467. } 468. if(Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)/* in bubble */) { 469. You_cant("write in thin air!"); 470. return(0); 471. } 472. if (cantwield(youmonst.data)) { 473. You_cant("even hold anything!"); 474. return(0); 475. } 476. if (check_capacity((char *)0)) return (0); 477. 478. /* One may write with finger, or weapon, or wand, or..., or... 479. * Edited by GAN 10/20/86 so as not to change weapon wielded. 480. */ 481. 482. otmp = getobj(styluses, "write with"); 483. if(!otmp) return(0); /* otmp == zeroobj if fingers */ 484. 485. if (otmp == &zeroobj) writer = makeplural(body_part(FINGER)); 486. else writer = xname(otmp); 487. 488. /* There's no reason you should be able to write with a wand 489. * while both your hands are tied up. 490. */ 491. if (!freehand() && otmp != uwep && !otmp->owornmask) { 492. You("have no free %s to write with!", body_part(HAND)); 493. return(0); 494. } 495. 496. if (jello) { 497. You("tickle %s with your %s.", mon_nam(u.ustuck), writer); 498. Your("message dissolves..."); 499. return(0); 500. } 501. if (otmp->oclass != WAND_CLASS && !can_reach_floor()) { 502. You_cant("reach the %s!", surface(u.ux,u.uy)); 503. return(0); 504. } 505. if (IS_ALTAR(levl[u.ux][u.uy].typ)) { 506. You("make a motion towards the altar with your %s.", writer); 507. altar_wrath(u.ux, u.uy); 508. return(0); 509. } 510. 511. /* SPFX for items */ 512. 513. switch (otmp->oclass) { 514. default: 515. case AMULET_CLASS: 516. case CHAIN_CLASS: 517. case POTION_CLASS: 518. case GOLD_CLASS: 519. break; 520. 521. case RING_CLASS: 522. /* "diamond" rings and others should work */ 523. case GEM_CLASS: 524. /* diamonds & other hard gems should work */ 525. if (objects[otmp->otyp].oc_tough) { 526. type = ENGRAVE; 527. break; 528. } 529. break; 530. 531. case ARMOR_CLASS: 532. if (is_boots(otmp)) { 533. type = DUST; 534. break; 535. } 536. /* fall through */ 537. /* Objects too large to engrave with */ 538. case BALL_CLASS: 539. case ROCK_CLASS: 540. You_cant("engrave with such a large object!"); 541. ptext = FALSE; 542. break; 543. 544. /* Objects too silly to engrave with */ 545. case FOOD_CLASS: 546. case SCROLL_CLASS: 547. case SPBOOK_CLASS: 548. Your("%s would get %s.", xname(otmp), 549. is_ice(u.ux,u.uy) ? "all frosty" : "too dirty"); 550. ptext = FALSE; 551. break; 552. 553. case RANDOM_CLASS: /* This should mean fingers */ 554. break; 555. 556. /* The charge is removed from the wand before prompting for 557. * the engraving text, because all kinds of setup decisions 558. * and pre-engraving messages are based upon knowing what type 559. * of engraving the wand is going to do. Also, the player 560. * will have potentially seen "You wrest .." message, and 561. * therefore will know they are using a charge. 562. */ 563. case WAND_CLASS: 564. if (zappable(otmp)) { 565. check_unpaid(otmp); 566. zapwand = TRUE; 567. if (Levitation) ptext = FALSE; 568. 569. switch (otmp->otyp) { 570. /* DUST wands */ 571. default: 572. break; 573. 574. /* NODIR wands */ 575. case WAN_LIGHT: 576. case WAN_SECRET_DOOR_DETECTION: 577. case WAN_CREATE_MONSTER: 578. case WAN_WISHING: 579. case WAN_ENLIGHTENMENT: 580. zapnodir(otmp); 581. break; 582. 583. /* IMMEDIATE wands */ 584. /* If wand is "IMMEDIATE", remember to affect the 585. * previous engraving even if turning to dust. 586. */ 587. case WAN_STRIKING: 588. Strcpy(post_engr_text, 589. "The wand unsuccessfully fights your attempt to write!" 590. ); 591. break; 592. case WAN_SLOW_MONSTER: 593. if (!Blind) { 594. Sprintf(post_engr_text, 595. "The bugs on the %s slow down!", 596. surface(u.ux, u.uy)); 597. } 598. break; 599. case WAN_SPEED_MONSTER: 600. if (!Blind) { 601. Sprintf(post_engr_text, 602. "The bugs on the %s speed up!", 603. surface(u.ux, u.uy)); 604. } 605. break; 606. case WAN_POLYMORPH: 607. if(oep) { 608. if (!Blind) { 609. type = (xchar)0; /* random */ 610. (void) random_engraving(buf); 611. } 612. dengr = TRUE; 613. } 614. break; 615. case WAN_NOTHING: 616. case WAN_UNDEAD_TURNING: 617. case WAN_OPENING: 618. case WAN_LOCKING: 619. case WAN_PROBING: 620. break; 621. 622. /* RAY wands */ 623. case WAN_MAGIC_MISSILE: 624. ptext = TRUE; 625. if (!Blind) { 626. Sprintf(post_engr_text, 627. "The %s is riddled by bullet holes!", 628. surface(u.ux, u.uy)); 629. } 630. break; 631. 632. /* can't tell sleep from death - Eric Backus */ 633. case WAN_SLEEP: 634. case WAN_DEATH: 635. if (!Blind) { 636. Sprintf(post_engr_text, 637. "The bugs on the %s stop moving!", 638. surface(u.ux, u.uy)); 639. } 640. break; 641. 642. case WAN_COLD: 643. if (!Blind) 644. Strcpy(post_engr_text, 645. "A few ice cubes drop from the wand."); 646. if(!oep || (oep->engr_type != BURN)) 647. break; 648. case WAN_CANCELLATION: 649. case WAN_MAKE_INVISIBLE: 650. if(oep) { 651. if (!Blind) 652. pline_The("engraving on the %s vanishes!", 653. surface(u.ux,u.uy)); 654. dengr = TRUE; 655. } 656. break; 657. case WAN_TELEPORTATION: 658. if (oep) { 659. if (!Blind) 660. pline_The("engraving on the %s vanishes!", 661. surface(u.ux,u.uy)); 662. teleengr = TRUE; 663. } 664. break; 665. 666. /* type = ENGRAVE wands */ 667. case WAN_DIGGING: 668. ptext = TRUE; 669. type = ENGRAVE; 670. if(!objects[otmp->otyp].oc_name_known) { 671. if (flags.verbose) 672. pline("This %s is a wand of digging!", 673. xname(otmp)); 674. doknown = TRUE; 675. } 676. if (!Blind) 677. Strcpy(post_engr_text, 678. is_ice(u.ux,u.uy) ? 679. "Ice chips fly up from the ice surface!" : 680. "Gravel flies up from the floor."); 681. else 682. Strcpy(post_engr_text, "You hear drilling!"); 683. break; 684. 685. /* type = BURN wands */ 686. case WAN_FIRE: 687. ptext = TRUE; 688. type = BURN; 689. if(!objects[otmp->otyp].oc_name_known) { 690. if (flags.verbose) 691. pline("This %s is a wand of fire!", xname(otmp)); 692. doknown = TRUE; 693. } 694. Strcpy(post_engr_text, 695. Blind ? "You feel the wand heat up." : 696. "Flames fly from the wand."); 697. break; 698. case WAN_LIGHTNING: 699. ptext = TRUE; 700. type = BURN; 701. if(!objects[otmp->otyp].oc_name_known) { 702. if (flags.verbose) 703. pline("This %s is a wand of lightning!", 704. xname(otmp)); 705. doknown = TRUE; 706. } 707. if (!Blind) { 708. Strcpy(post_engr_text, 709. "Lightning arcs from the wand."); 710. doblind = TRUE; 711. } else 712. Strcpy(post_engr_text, "You hear crackling!"); 713. break; 714. 715. /* type = MARK wands */ 716. /* type = BLOOD wands */ 717. } 718. } else /* end if zappable */ 719. if (!can_reach_floor()) { 720. You_cant("reach the %s!", surface(u.ux,u.uy)); 721. return(0); 722. } 723. break; 724. 725. case WEAPON_CLASS: 726. if(is_blade(otmp)) 727. if ((int)otmp->spe > -3) 728. type = ENGRAVE; 729. else 730. Your("%s too dull for engraving.", aobjnam(otmp,"are")); 731. break; 732. 733. case TOOL_CLASS: 734. if(otmp == ublindf) { 735. pline( 736. "That is a bit difficult to engrave with, don't you think?"); 737. return(0); 738. } 739. switch (otmp->otyp) { 740. case MAGIC_MARKER: 741. if (otmp->spe <= 0) 742. Your("marker has dried out."); 743. else 744. type = MARK; 745. break; 746. case TOWEL: 747. /* Can't really engrave with a towel */ 748. ptext = FALSE; 749. if (oep) 750. if ((oep->engr_type == DUST ) || 751. (oep->engr_type == BLOOD) || 752. (oep->engr_type == MARK )) { 753. if (!Blind) 754. You("wipe out the message here."); 755. else 756. Your("%s gets %s.", xname(otmp), 757. is_ice(u.ux,u.uy) ? 758. "frosty" : "dusty"); 759. dengr = TRUE; 760. } else 761. Your("%s can't wipe out this engraving.", 762. xname(otmp)); 763. else 764. Your("%s gets %s.", xname(otmp), 765. is_ice(u.ux,u.uy) ? "frosty" : "dusty"); 766. break; 767. default: 768. break; 769. } 770. break; 771. 772. case VENOM_CLASS: 773. #ifdef WIZARD 774. if (wizard) { 775. pline("Writing a poison pen letter??"); 776. break; 777. } 778. #endif 779. case ILLOBJ_CLASS: 780. impossible("You're engraving with an illegal object!"); 781. break; 782. } 783. 784. /* End of implement setup */ 785. 786. /* Identify stylus */ 787. if (doknown) { 788. makeknown(otmp->otyp); 789. more_experienced(0,10); 790. } 791. 792. if (teleengr) { 793. rloc_engr(oep); 794. oep = (struct engr *)0; 795. } 796. 797. if (dengr) { 798. del_engr(oep); 799. oep = (struct engr *)0; 800. } 801. 802. /* Something has changed the engraving here */ 803. if (*buf) { 804. make_engr_at(u.ux, u.uy, buf, moves, type); 805. pline_The("engraving now reads: \"%s\".", buf); 806. ptext = FALSE; 807. } 808. 809. if (zapwand && (otmp->spe < 0)) { 810. pline("%s %sturns to dust.", 811. The(xname(otmp)), Blind ? "" : "glows violently, then "); 812. You("are not going to get anywhere trying to write in the %s with your dust.", 813. is_ice(u.ux,u.uy) ? "frost" : "dust"); 814. useup(otmp); 815. ptext = FALSE; 816. } 817. 818. if (!ptext) { /* Early exit for some implements. */ 819. if (otmp->oclass == WAND_CLASS && !can_reach_floor()) 820. You_cant("reach the %s!", surface(u.ux,u.uy)); 821. return(1); 822. } 823. 824. /* Special effects should have deleted the current engraving (if 825. * possible) by now. 826. */ 827. 828. if (oep) { 829. register char c = 'n'; 830. 831. /* Give player the choice to add to engraving. */ 832. 833. if ( (type == oep->engr_type) && (!Blind || 834. (oep->engr_type == BURN) || (oep->engr_type == ENGRAVE)) ) { 835. c = yn_function("Do you want to add to the current engraving?", 836. ynqchars, 'y'); 837. if (c == 'q') { 838. pline("Never mind."); 839. return(0); 840. } 841. } 842. 843. if (c == 'n' || Blind) { 844. 845. if( (oep->engr_type == DUST) || (oep->engr_type == BLOOD) || 846. (oep->engr_type == MARK) ) { 847. if (!Blind) { 848. You("wipe out the message that was %s here.", 849. ((oep->engr_type == DUST) ? "written in the dust" : 850. ((oep->engr_type == BLOOD) ? "scrawled in blood" : 851. "written"))); 852. del_engr(oep); 853. oep = (struct engr *)0; 854. } else 855. /* Don't delete engr until after we *know* we're engraving */ 856. eow = TRUE; 857. } else 858. if ( (type == DUST) || (type == MARK) || (type == BLOOD) ) { 859. You( 860. "cannot wipe out the message that is %s the %s here.", 861. oep->engr_type == BURN ? 862. (is_ice(u.ux,u.uy) ? "melted into" : "burned into") : 863. "engraved in", surface(u.ux,u.uy)); 864. return(1); 865. } else 866. if ( (type != oep->engr_type) || (c == 'n') ) { 867. if (!Blind || can_reach_floor()) 868. You("will overwrite the current message."); 869. eow = TRUE; 870. } 871. } 872. } 873. 874. eloc = surface(u.ux,u.uy); 875. switch(type){ 876. default: 877. everb = (oep && !eow ? "add to the weird writing on" : 878. "write strangely on"); 879. break; 880. case DUST: 881. everb = (oep && !eow ? "add to the writing in" : 882. "write in"); 883. eloc = is_ice(u.ux,u.uy) ? "frost" : "dust"; 884. break; 885. case ENGRAVE: 886. everb = (oep && !eow ? "add to the engraving in" : 887. "engrave in"); 888. break; 889. case BURN: 890. everb = (oep && !eow ? 891. ( is_ice(u.ux,u.uy) ? "add to the text melted into" : 892. "add to the text burned into") : 893. ( is_ice(u.ux,u.uy) ? "melt into" : "burn into")); 894. break; 895. case MARK: 896. everb = (oep && !eow ? "add to the graffiti on" : 897. "scribble on"); 898. break; 899. case BLOOD: 900. everb = (oep && !eow ? "add to the scrawl on" : 901. "scrawl on"); 902. break; 903. } 904. 905. /* Tell adventurer what is going on */ 906. if (otmp != &zeroobj) 907. You("%s the %s with %s.", everb, eloc, doname(otmp)); 908. else 909. You("%s the %s with your %s.", everb, eloc, 910. makeplural(body_part(FINGER))); 911. 912. /* Prompt for engraving! */ 913. Sprintf(qbuf,"What do you want to %s the %s here?", everb, eloc); 914. getlin(qbuf, ebuf); 915. 916. /* Mix up engraving if surface or state of mind is unsound. */ 917. /* Original kludge by stewr 870708. modified by njm 910722. */ 918. for (sp = ebuf; *sp; sp++) 919. if ( ((type == DUST || type == BLOOD) && !rn2(25)) || 920. (Blind && !rn2(9)) || (Confusion && !rn2(12)) || 921. (Stunned && !rn2(4)) || (Hallucination && !rn2(1)) ) 922. *sp = '!' + rn2(93); /* ASCII-code only */ 923. 924. /* Count the actual # of chars engraved not including spaces */ 925. len = strlen(ebuf); 926. 927. for (sp = ebuf, spct = 0; *sp; sp++) if (isspace(*sp)) spct++; 928. 929. if ( (len == spct) || index(ebuf, '\033') ) { 930. if (zapwand) { 931. if (!Blind) 932. pline("%s glows, then fades.", The(xname(otmp))); 933. return(1); 934. } else { 935. pline("Never mind."); 936. return(0); 937. } 938. } 939. 940. len -= spct; 941. 942. /* Previous engraving is overwritten */ 943. if (eow) { 944. del_engr(oep); 945. oep = (struct engr *)0; 946. } 947. 948. /* Figure out how long it took to engrave, and if player has 949. * engraved too much. 950. */ 951. switch(type){ 952. default: 953. multi = -(len/10); 954. if (multi) nomovemsg = "You finish your weird engraving."; 955. break; 956. case DUST: 957. multi = -(len/10); 958. if (multi) nomovemsg = "You finish writing in the dust."; 959. break; 960. case ENGRAVE: 961. multi = -(len/10); 962. if ((otmp->oclass == WEAPON_CLASS) && 963. ((otmp->otyp != ATHAME) || otmp->cursed)) { 964. multi = -len; 965. maxelen = ((otmp->spe + 3) * 2) + 1; 966. /* -2 = 3, -1 = 5, 0 = 7, +1 = 9, +2 = 11 967. * Note: this does not allow a +0 anything (except 968. * an athame) to engrave "Elbereth" all at once. 969. * However, you could now engrave "Elb", then 970. * "ere", then "th". 971. */ 972. Your("%s dull.", aobjnam(otmp, "get")); 973. if (len > maxelen) { 974. multi = -maxelen; 975. otmp->spe = -3; 976. } else 977. if (len > 1) otmp->spe -= len >> 1; 978. else otmp->spe -= 1; /* Prevent infinite engraving */ 979. } else 980. if ( (otmp->oclass == RING_CLASS) || 981. (otmp->oclass == GEM_CLASS) ) 982. multi = -len; 983. if (multi) nomovemsg = "You finish engraving."; 984. break; 985. case BURN: 986. multi = -(len/10); 987. if (multi) 988. nomovemsg = is_ice(u.ux,u.uy) ? 989. "You finish melting your message into the ice.": 990. "You finish burning your message into the floor."; 991. break; 992. case MARK: 993. multi = -(len/10); 994. if ((otmp->oclass == TOOL_CLASS) && 995. (otmp->otyp == MAGIC_MARKER)) { 996. maxelen = (otmp->spe) * 2; /* one charge / 2 letters */ 997. if (len > maxelen) { 998. Your("marker dries out."); 999. otmp->spe = 0; 1000. multi = -(maxelen/10); 1001. } else 1002. if (len > 1) otmp->spe -= len >> 1; 1003. else otmp->spe -= 1; /* Prevent infinite grafitti */ 1004. } 1005. if (multi) nomovemsg = "You finish defacing the dungeon."; 1006. break; 1007. case BLOOD: 1008. multi = -(len/10); 1009. if (multi) nomovemsg = "You finish scrawling."; 1010. break; 1011. } 1012. 1013. /* Chop engraving down to size if necessary */ 1014. if (len > maxelen) { 1015. for (sp = ebuf; (maxelen && *sp); sp++) 1016. if (!isspace(*sp)) maxelen--; 1017. if (!maxelen && *sp) { 1018. *sp = (char)0; 1019. if (multi) nomovemsg = "You cannot write any more."; 1020. You("only are able to write \"%s\"", ebuf); 1021. } 1022. } 1023. 1024. /* Add to existing engraving */ 1025. if (oep) Strcpy(buf, oep->engr_txt); 1026. 1027. (void) strncat(buf, ebuf, (BUFSZ - (int)strlen(buf) - 1)); 1028. 1029. make_engr_at(u.ux, u.uy, buf, (moves - multi), type); 1030. 1031. if (post_engr_text[0]) pline(post_engr_text); 1032. 1033. if (doblind && !resists_blnd(&youmonst)) { 1034. You("are blinded by the flash!"); 1035. make_blinded((long)rnd(50),FALSE); 1036. } 1037. 1038. u.uconduct.literate++; 1039. 1040. return(1); 1041. } 1042. 1043. void 1044. save_engravings(fd, mode) 1045. int fd, mode; 1046. { 1047. register struct engr *ep = head_engr; 1048. register struct engr *ep2; 1049. unsigned no_more_engr = 0; 1050. 1051. while (ep) { 1052. ep2 = ep->nxt_engr; 1053. if (ep->engr_lth && ep->engr_txt[0] && perform_bwrite(mode)) { 1054. bwrite(fd, (genericptr_t)&(ep->engr_lth), sizeof(ep->engr_lth)); 1055. bwrite(fd, (genericptr_t)ep, sizeof(struct engr) + ep->engr_lth); 1056. } 1057. if (release_data(mode)) 1058. dealloc_engr(ep); 1059. ep = ep2; 1060. } 1061. if (perform_bwrite(mode)) 1062. bwrite(fd, (genericptr_t)&no_more_engr, sizeof no_more_engr); 1063. if (release_data(mode)) 1064. head_engr = 0; 1065. } 1066. 1067. void 1068. rest_engravings(fd) 1069. int fd; 1070. { 1071. register struct engr *ep; 1072. unsigned lth; 1073. 1074. head_engr = 0; 1075. while(1) { 1076. mread(fd, (genericptr_t) <h, sizeof(unsigned)); 1077. if(lth == 0) return; 1078. ep = newengr(lth); 1079. mread(fd, (genericptr_t) ep, sizeof(struct engr) + lth); 1080. ep->nxt_engr = head_engr; 1081. head_engr = ep; 1082. ep->engr_txt = (char *) (ep + 1); /* Andreas Bormann */ 1083. /* mark as finished for bones levels -- no problem for 1084. * normal levels as the player must have finished engraving 1085. * to be able to move again */ 1086. ep->engr_time = moves; 1087. } 1088. } 1089. 1090. void 1091. del_engr(ep) 1092. register struct engr *ep; 1093. { 1094. if (ep == head_engr) { 1095. head_engr = ep->nxt_engr; 1096. } else { 1097. register struct engr *ept; 1098. 1099. for (ept = head_engr; ept; ept = ept->nxt_engr) 1100. if (ept->nxt_engr == ep) { 1101. ept->nxt_engr = ep->nxt_engr; 1102. break; 1103. } 1104. if (!ept) { 1105. impossible("Error in del_engr?"); 1106. return; 1107. } 1108. } 1109. dealloc_engr(ep); 1110. } 1111. 1112. /* randomly relocate an engraving */ 1113. void 1114. rloc_engr(ep) 1115. struct engr *ep; 1116. { 1117. int tx, ty, tryct = 200; 1118. 1119. do { 1120. if (--tryct < 0) return; 1121. tx = rn1(COLNO-3,2); 1122. ty = rn2(ROWNO); 1123. } while (engr_at(tx, ty) || 1124. !goodpos(tx, ty, (struct monst *)0)); 1125. 1126. ep->engr_x = tx; 1127. ep->engr_y = ty; 1128. } 1129. 1130. #endif /* OVLB */ 1131. 1132. /*engrave.c*/
|