abstract
| - Below is the full text to engrave.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.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.0 89/06/12 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. 7. static void del_engr P((struct engr *)); 8. 9. struct engr { 10. struct engr *nxt_engr; 11. char *engr_txt; 12. xchar engr_x, engr_y; 13. unsigned engr_lth; /* for save & restore; not length of text */ 14. long engr_time; /* moment engraving was (will be) finished */ 15. xchar engr_type; 16. #define DUST 1 17. #define ENGRAVE 2 18. #define BURN 3 19. #define MARK 4 20. #define POLY 5 /* temporary type - for polymorphing engraving */ 21. } *head_engr; 22. 23. /* random engravings */ 24. const char *random_engr[] = 25. {"Elbereth", "ad ae?ar um", 26. "?la? ?as he??", 27. /* more added by Eric Backus */ 28. "?ilroy wa? h?re", "?ala??iel", 29. "Fo? a ?ood time c?ll 6?6-4311", 30. /* some other famous engravings -3. */ 31. "Lasc?ate o?ni sp?ranz? o vo? c?'en?rate", 32. "Y?u won?t get i? up ?he ste?s", 33. "A.S. ->"}; 34. 35. static struct engr * 36. engr_at(x,y) register xchar x,y; { 37. register struct engr *ep = head_engr; 38. while(ep) { 39. if(x == ep->engr_x && y == ep->engr_y) 40. return(ep); 41. ep = ep->nxt_engr; 42. } 43. return((struct engr *) 0); 44. } 45. 46. #ifdef ELBERETH 47. int 48. sengr_at(s,x,y) 49. register char *s; 50. register xchar x,y; 51. { 52. register struct engr *ep = engr_at(x,y); 53. register char *t; 54. register int n; 55. 56. if(ep && ep->engr_time <= moves) { 57. t = ep->engr_txt; 58. /* 59. if(!strcmp(s,t)) return(1); 60. */ 61. n = strlen(s); 62. while(*t) { 63. if(!strncmp(s,t,n)) return(1); 64. t++; 65. } 66. } 67. return(0); 68. } 69. #endif 70. 71. void 72. u_wipe_engr(cnt) 73. register int cnt; 74. { 75. if(!u.uswallow && !Levitation) 76. wipe_engr_at(u.ux, u.uy, cnt); 77. } 78. 79. void 80. wipe_engr_at(x,y,cnt) register xchar x,y,cnt; { 81. register struct engr *ep = engr_at(x,y); 82. register int lth,pos; 83. char ch; 84. if(ep){ 85. if(ep->engr_type != BURN) { 86. if(ep->engr_type != DUST) { 87. cnt = rn2(1 + 50/(cnt+1)) ? 0 : 1; 88. } 89. lth = strlen(ep->engr_txt); 90. if(lth && cnt > 0 ) { 91. while(cnt--) { 92. pos = rn2(lth); 93. if((ch = ep->engr_txt[pos]) == ' ') 94. continue; 95. ep->engr_txt[pos] = (ch != '?') ? '?' : ' '; 96. } 97. } 98. while(lth && ep->engr_txt[lth-1] == ' ') 99. ep->engr_txt[--lth] = 0; 100. while(ep->engr_txt[0] == ' ') 101. ep->engr_txt++; 102. if(!ep->engr_txt[0]) del_engr(ep); 103. } 104. } 105. } 106. 107. void 108. read_engr_at(x,y) register int x,y; { 109. register struct engr *ep = engr_at(x,y); 110. register int canfeel; 111. if(ep && ep->engr_txt[0]) { 112. switch(ep->engr_type) { 113. case DUST: 114. if(!Blind) pline("Something is written here in the dust."); 115. canfeel = 0; 116. break; 117. case ENGRAVE: 118. pline("Something is engraved here on the floor."); 119. canfeel = 1; 120. break; 121. case BURN: 122. pline("Some text has been burned here in the floor."); 123. canfeel = 1; 124. break; 125. case MARK: 126. if(!Blind) pline("There's some graffiti here on the floor."); 127. canfeel = 0; 128. break; 129. default: 130. impossible("Something is written in a very strange way."); 131. canfeel = 1; 132. } 133. if (canfeel || !Blind) 134. You("%s: \"%s\".", 135. (Blind) ? "feel the words" : "read", ep->engr_txt); 136. } 137. } 138. 139. void 140. make_engr_at(x,y,s) 141. register int x,y; 142. register char *s; 143. { 144. register struct engr *ep; 145. 146. if(ep = engr_at(x,y)) 147. del_engr(ep); 148. ep = (struct engr *) 149. alloc((unsigned)(sizeof(struct engr) + strlen(s) + 1)); 150. ep->nxt_engr = head_engr; 151. head_engr = ep; 152. ep->engr_x = x; 153. ep->engr_y = y; 154. ep->engr_txt = (char *)(ep + 1); 155. Strcpy(ep->engr_txt, s); 156. ep->engr_time = 0; 157. ep->engr_type = DUST; 158. ep->engr_lth = strlen(s) + 1; 159. } 160. 161. /* 162. * freehand - returns true if player has a free hand 163. */ 164. int 165. freehand(){ 166. 167. return(!uwep || 168. !uwep->cursed || 169. (!bimanual(uwep) && (!uarms || !uarms->cursed))); 170. /* if ((uwep && bimanual(uwep)) || 171. (uwep && uarms)) 172. return(0); 173. else 174. return(1);*/ 175. } 176. 177. static const char styluses[] = { '#', '-', TOOL_SYM, WEAPON_SYM, WAND_SYM, 0 }; 178. static const char too_large[] = { ARMOR_SYM, BALL_SYM, ROCK_SYM, 0 }; 179. static const char paper[] = { SCROLL_SYM, 180. #ifdef SPELLS 181. SPBOOK_SYM, 182. #endif 183. 0 }; 184. 185. int 186. doengrave(){ 187. register int len, tmp; 188. register char *sp, *sptmp; 189. register struct engr *ep, *oep = engr_at(u.ux,u.uy); 190. char buf[BUFSZ]; 191. xchar type, polytype = 0; 192. int spct; /* number of leading spaces */ 193. register struct obj *otmp; 194. multi = 0; 195. 196. if(u.uswallow) { 197. pline("What would you write? \"Jonah was here\"?"); 198. return(0); 199. } 200. 201. /* one may write with finger, weapon or wand */ 202. /* edited by GAN 10/20/86 so as not to change 203. * weapon wielded. 204. */ 205. otmp = getobj(styluses, "write with"); 206. if(!otmp) return(0); 207. 208. /* There's no reason you should be able to write with a wand 209. * while both your hands are tied up. 210. */ 211. if (!freehand() && otmp != uwep) { 212. You("have no free %s to write with!", body_part(HAND)); 213. return(0); 214. } 215. #ifdef POLYSELF 216. if (cantwield(uasmon)) { 217. You("can't even hold anything!"); 218. return(0); 219. } 220. #endif 221. if(otmp != &zeroobj && index(too_large,otmp->olet)) { 222. You("can't engrave with such a large object!"); 223. return(1); 224. } 225. 226. if(otmp != &zeroobj && index(paper,otmp->olet)) { 227. Your("%s would get dirty.",xname(otmp)); 228. return(1); 229. } 230. 231. if(Levitation && otmp->olet != WAND_SYM){ /* riv05!a3 */ 232. You("can't reach the floor!"); 233. return(0); 234. } 235. 236. if(otmp == &zeroobj) { 237. You("write in the dust with your %s.", 238. makeplural(body_part(FINGER))); 239. type = DUST; 240. } else if(otmp->olet == WAND_SYM && zappable(otmp)) { 241. /* changed so any wand gets zapped out, but fire 242. * wands become known. 243. */ 244. if((objects[otmp->otyp].bits & NODIR)) { 245. zapnodir(otmp); 246. type = DUST; 247. } else { 248. switch(otmp->otyp) { 249. case WAN_LIGHTNING: 250. if(!objects[otmp->otyp].oc_name_known) { 251. if(flags.verbose) 252. pline("The %s is a wand of lightning!", 253. xname(otmp)); 254. makeknown(otmp->otyp); 255. more_experienced(0,10); 256. } 257. type = BURN; 258. break; 259. case WAN_FIRE: 260. if(!objects[otmp->otyp].oc_name_known) { 261. if(flags.verbose) 262. pline("The %s is a wand of fire!", 263. xname(otmp)); 264. makeknown(otmp->otyp); 265. more_experienced(0,10); 266. } 267. type = BURN; 268. break; 269. case WAN_DIGGING: 270. if(!objects[otmp->otyp].oc_name_known) { 271. if(flags.verbose) 272. pline("The %s is a wand of digging!", 273. xname(otmp)); 274. makeknown(otmp->otyp); 275. more_experienced(0,10); 276. } 277. type = ENGRAVE; 278. break; 279. case WAN_POLYMORPH: 280. if(oep) { 281. del_engr(oep); 282. oep = 0; 283. type = POLY; 284. } else 285. type = DUST; 286. break; 287. case WAN_COLD: 288. type = DUST; 289. if(!oep || (oep->engr_type != BURN)) 290. break; 291. case WAN_CANCELLATION: 292. case WAN_MAKE_INVISIBLE: 293. if(!oep) { /* Eric Backus */ 294. type = DUST; 295. break; 296. } 297. del_engr(oep); 298. pline("The engraving on the floor vanishes!"); 299. return(1); 300. /* break; */ 301. case WAN_TELEPORTATION: 302. if(!oep) 303. type = DUST; 304. else { 305. register int tx,ty; 306. 307. do { 308. tx = rn1(COLNO-3,2); 309. ty = rn2(ROWNO); 310. } while(!goodpos(tx,ty)); 311. oep->engr_x = tx; 312. oep->engr_y = ty; 313. pline("The engraving on the floor vanishes!"); 314. return(1); 315. } 316. break; 317. default: 318. type = DUST; 319. } 320. } 321. if(type == DUST) 322. You("write in the dust with %s.", 323. doname(otmp)); 324. 325. } else { 326. if(otmp->otyp == DAGGER || 327. #ifdef WORM 328. otmp->otyp == CRYSKNIFE || 329. #endif 330. is_sword(otmp) || otmp->otyp == AXE) { 331. type = ENGRAVE; 332. if((int)otmp->spe <= -3) { 333. Your("%s too dull for engraving.", 334. aobjnam(otmp, "are")); 335. type = DUST; 336. /* following messaged added 10/20/86 - GAN */ 337. You("write in the dust with %s.", 338. doname(otmp)); 339. } else 340. You("engrave with %s.", doname(otmp)); 341. } else if(otmp->otyp == MAGIC_MARKER) { 342. if(otmp->spe <= 0) { 343. Your("marker is dried out."); 344. You("write in the dust with the marker."); 345. type = DUST; 346. } else { 347. You("write with %s.", doname(otmp)); 348. type = MARK; 349. } 350. } else { 351. You("write in the dust with %s.", 352. doname(otmp)); 353. type = DUST; 354. } 355. } 356. 357. if(type != POLY && oep && oep->engr_type == DUST){ 358. You("wipe out the message that was written here."); 359. del_engr(oep); 360. oep = 0; 361. } 362. if(type == DUST && oep) { 363. You("cannot wipe out the message that is %s in the rock.", 364. (oep->engr_type == BURN) ? "burned" : 365. (oep->engr_type == ENGRAVE) ? "engraved" : "scribbled"); 366. return(1); 367. } 368. if(type == POLY) { 369. polytype = rnd(4); 370. Strcpy(buf,random_engr[rn2(SIZE(random_engr))]); 371. switch(polytype){ 372. case DUST: 373. pline("\"%s\" is now written on the ground.",buf); 374. break; 375. case ENGRAVE: 376. pline("\"%s\" is now engraved in the rock.",buf); 377. break; 378. case BURN: 379. pline("\"%s\" is now burned in the rock.",buf); 380. break; 381. case MARK: 382. pline("\"%s\" is now scribbled on the rock.",buf); 383. break; 384. default: 385. impossible("\"%s\" is now written in a very strange way.", 386. buf); 387. } 388. } else { 389. pline("What do you want to %s on the floor here? ", 390. (type == ENGRAVE) ? "engrave" : (type == BURN) ? "burn" : "write"); 391. getlin(buf); 392. clrlin(); 393. } 394. spct = 0; 395. sp = buf; 396. while(*sp == ' ') spct++, sp++; 397. len = strlen(sp); 398. if(!len || *buf == '\033') { 399. /* changed by GAN 11/01/86 to not recharge wand */ 400. return(1); 401. } 402. if(otmp->otyp == WAN_FIRE) { 403. if (!Blind) pline("Flames fly from the wand."); 404. else You("feel the wand heat up."); 405. } else if(otmp->otyp == WAN_LIGHTNING) { 406. if (!Blind) { 407. pline("Lightning arcs from the wand."); 408. You("are blinded by the flash!"); 409. make_blinded((long)rnd(50),FALSE); 410. } else You("hear crackling!"); 411. } else if(otmp->otyp == WAN_DIGGING) { 412. if (!Blind) pline("Gravel flies up from the floor."); 413. else You("hear drilling!"); 414. } 415. /* kludge by stewr 870708 */ 416. for (sptmp = sp, tmp=0; !(tmp == len); sptmp++,tmp++) { 417. if (((type == DUST) && !rn2(25)) 418. || (Blind && !rn2(12)) 419. || (Confusion && !rn2(3))) { 420. *sptmp = '!' + rn2(93); /* ASCII-code only */ 421. } 422. } 423. 424. switch(type) { 425. case DUST: 426. case BURN: 427. if(len > 15) { 428. multi = -(len/10); 429. nomovemsg = "You finish writing."; 430. } 431. break; 432. case ENGRAVE: 433. case MARK: 434. { int len2; 435. 436. if(type == ENGRAVE) 437. len2 = (otmp->spe + 3) * 2 + 1; 438. else 439. len2 = (otmp->spe) * 2; 440. nomovemsg = "You finish writing."; 441. if(type != MARK) 442. nomovemsg = "You finish engraving."; 443. if(otmp->olet != WAND_SYM) { 444. if(otmp->olet == WEAPON_SYM) 445. Your("%s dull.", 446. aobjnam(otmp, "get")); 447. if(len2 < len) { 448. len = len2; 449. sp[len] = 0; 450. if(type == ENGRAVE) { 451. otmp->spe = -3; 452. } else { 453. Your("marker dries out!"); 454. otmp->spe = 0; 455. } 456. /* next line added by GAN 10/20/86 */ 457. You("only write \"%s\".", sp); 458. nomovemsg = "You cannot write more."; 459. } else 460. otmp->spe -= len >> 1; 461. if(type == MARK) 462. multi = -(len/10); 463. else 464. multi = -len; 465. } else 466. multi = -(len/10); 467. if (multi == 0) 468. nomovemsg = (char *)0; 469. } 470. break; 471. case POLY: 472. type = polytype; 473. multi = 0; 474. break; 475. } 476. if(oep) len += strlen(oep->engr_txt) + spct; 477. ep = (struct engr *) alloc((unsigned)(sizeof(struct engr) + len + 1)); 478. ep->nxt_engr = head_engr; 479. head_engr = ep; 480. ep->engr_x = u.ux; 481. ep->engr_y = u.uy; 482. sp = (char *)(ep + 1); /* (char *)ep + sizeof(struct engr) */ 483. ep->engr_txt = sp; 484. if(oep) { 485. Strcpy(sp, oep->engr_txt); 486. Strcat(sp, buf); 487. del_engr(oep); 488. } else 489. Strcpy(sp, buf); 490. ep->engr_lth = len+1; 491. ep->engr_type = type; 492. ep->engr_time = moves-multi; 493. 494. /* kludge to protect pline against excessively long texts */ 495. if(len > BUFSZ-20) sp[BUFSZ-20] = 0; 496. 497. /* cute messages for odd wands */ 498. switch(otmp->otyp) { 499. case WAN_SLOW_MONSTER: 500. pline("The bugs on the ground slow down!"); 501. break; 502. case WAN_SPEED_MONSTER: 503. pline("The bugs on the ground speed up!"); 504. break; 505. case WAN_MAGIC_MISSILE: 506. pline("The ground is riddled by bullet holes!"); 507. break; 508. case WAN_SLEEP: 509. case WAN_DEATH: /* can't tell sleep from death - Eric Backus */ 510. pline("The bugs on the ground stop moving!"); 511. break; 512. case WAN_COLD: 513. pline("A few ice cubes drop from your %s.",xname(otmp)); 514. break; 515. case WAN_STRIKING: 516. pline("The %s unsuccessfully fights your attempt to write!",xname(otmp)); 517. } 518. 519. return(1); 520. } 521. 522. void 523. save_engravings(fd) int fd; { 524. register struct engr *ep = head_engr; 525. register struct engr *ep2; 526. while(ep) { 527. ep2 = ep->nxt_engr; 528. if(ep->engr_lth && ep->engr_txt[0]){ 529. bwrite(fd, (genericptr_t)&(ep->engr_lth), sizeof(ep->engr_lth)); 530. bwrite(fd, (genericptr_t)ep, sizeof(struct engr) + ep->engr_lth); 531. } 532. #if defined(DGK) && !defined(TOS) 533. if (!count_only) 534. #endif 535. free((genericptr_t) ep); 536. ep = ep2; 537. } 538. bwrite(fd, (genericptr_t)nul, sizeof(unsigned)); 539. #if defined(DGK) && !defined(TOS) 540. if (!count_only) 541. #endif 542. head_engr = 0; 543. } 544. 545. void 546. rest_engravings(fd) int fd; { 547. register struct engr *ep; 548. unsigned lth; 549. head_engr = 0; 550. while(1) { 551. mread(fd, (genericptr_t) <h, sizeof(unsigned)); 552. if(lth == 0) return; 553. ep = (struct engr *) alloc(sizeof(struct engr) + lth); 554. mread(fd, (genericptr_t) ep, sizeof(struct engr) + lth); 555. ep->nxt_engr = head_engr; 556. ep->engr_txt = (char *) (ep + 1); /* Andreas Bormann */ 557. head_engr = ep; 558. } 559. } 560. 561. static void 562. del_engr(ep) register struct engr *ep; { 563. register struct engr *ept; 564. if(ep == head_engr) 565. head_engr = ep->nxt_engr; 566. else { 567. for(ept = head_engr; ept; ept = ept->nxt_engr) { 568. if(ept->nxt_engr == ep) { 569. ept->nxt_engr = ep->nxt_engr; 570. goto fnd; 571. } 572. } 573. impossible("Error in del_engr?"); 574. return; 575. fnd: ; 576. } 577. free((genericptr_t) ep); 578. }
|