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