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