abstract
| - Below is the full text to engrave.c from the source code of NetHack 2.2a. To link to a particular line, write [[NetHack 2.2a/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.0 87/09/14 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_FIRE: 248. if(!objects[otmp->otyp].oc_name_known) { 249. pline("The %s is a wand of fire!", 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_DIGGING: 257. if(!objects[otmp->otyp].oc_name_known) { 258. pline("The %s is a wand of digging!", 259. xname(otmp)); 260. objects[otmp->otyp].oc_name_known = 1; 261. more_experienced(0,10); 262. } 263. type = ENGRAVE; 264. break; 265. case WAN_POLYMORPH: 266. if(oep) { 267. del_engr(oep); 268. oep = 0; 269. type = POLY; 270. } else 271. type = DUST; 272. break; 273. case WAN_COLD: 274. type = DUST; 275. if(!oep || (oep->engr_type != BURN)) 276. break; 277. case WAN_CANCELLATION: 278. case WAN_MAKE_INVISIBLE: 279. if(!oep) { /* Eric Backus */ 280. type = DUST; 281. break; 282. } 283. del_engr(oep); 284. pline("The engraving on the floor vanishes!"); 285. return(1); 286. break; 287. case WAN_TELEPORTATION: 288. if(!oep) 289. type = DUST; 290. else { 291. register tx,ty; 292. 293. do { 294. tx = rn1(COLNO-3,2); 295. ty = rn2(ROWNO); 296. } while(!goodpos(tx,ty)); 297. oep->engr_x = tx; 298. oep->engr_y = ty; 299. pline("The engraving on the floor vanishes!"); 300. return(1); 301. } 302. break; 303. default: 304. type = DUST; 305. } 306. } 307. if(type == DUST) 308. pline("You write in the dust with %s.", 309. doname(otmp)); 310. 311. } else { 312. if(otmp->otyp == DAGGER || otmp->otyp == TWO_HANDED_SWORD || 313. otmp->otyp == CRYSKNIFE || otmp->otyp == KATANA || 314. otmp->otyp == SCIMITAR || otmp->otyp == BROAD_SWORD || 315. otmp->otyp == SHORT_SWORD || 316. otmp->otyp == LONG_SWORD || otmp->otyp == AXE) { 317. type = ENGRAVE; 318. if((int)otmp->spe <= -3) { 319. pline("Your %s too dull for engraving.", 320. aobjnam(otmp, "are")); 321. type = DUST; 322. /* following messaged added 10/20/86 - GAN */ 323. pline("You write in the dust with %s.", 324. doname(otmp)); 325. } else 326. pline("You engrave with %s.", doname(otmp)); 327. #ifdef MARKER 328. } else if(otmp->otyp == MAGIC_MARKER) { 329. if(otmp->spe <= 0) { 330. pline("Your marker is dried out."); 331. pline("You write in the dust with the marker."); 332. type = DUST; 333. } else { 334. pline("You write with %s.", doname(otmp)); 335. type = MARK; 336. } 337. #endif 338. } else { 339. pline("You write in the dust with %s.", 340. doname(otmp)); 341. type = DUST; 342. } 343. } 344. 345. if(type != POLY && oep && oep->engr_type == DUST){ 346. pline("You wipe out the message that was written here."); 347. del_engr(oep); 348. oep = 0; 349. } 350. if(type == DUST && oep){ 351. pline("You cannot wipe out the message that is %s in the rock.", 352. (oep->engr_type == BURN) ? "burned" : (oep->engr_type == ENGRAVE)? "engraved" : "scribbled"); 353. return(1); 354. } 355. if(type == POLY) { 356. #ifdef MARKER 357. type = rnd(4); 358. #else 359. type = rnd(3); 360. #endif 361. strcpy(buf,random_engr[rn2(RAND_ENGRS)]); 362. switch(type){ 363. case DUST: 364. pline("\"%s\" is now written on the ground.",buf); 365. break; 366. case ENGRAVE: 367. pline("\"%s\" is now engraved in the rock.",buf); 368. break; 369. case BURN: 370. pline("\"%s\" is now burned in the rock.",buf); 371. break; 372. #ifdef MARKER 373. case MARK: 374. pline("\"%s\" is now scribbled on the rock.",buf); 375. break; 376. #endif 377. default: 378. impossible("\"%s\" is now written in a very strange way.", 379. buf); 380. } 381. } else { 382. pline("What do you want to %s on the floor here? ", 383. (type == ENGRAVE) ? "engrave" : (type == BURN) ? "burn" : "write"); 384. getlin(buf); 385. clrlin(); 386. } 387. spct = 0; 388. sp = buf; 389. while(*sp == ' ') spct++, sp++; 390. len = strlen(sp); 391. if(!len || *buf == '\033') { 392. /* changed by GAN 11/01/86 to not recharge wand */ 393. if(type == BURN) 394. pline("A few sparks fly from the wand of fire."); 395. else 396. if(otmp->otyp == WAN_DIGGING) 397. pline("Gravel flies up from the floor."); 398. return(1); 399. } 400. /* kludge by stewr 870708 */ 401. for (sptmp = sp, tmp=0; !(tmp == len); sptmp++,tmp++) { 402. if (((type == DUST) && !rn2(25)) 403. || (Blind && !rn2(12)) 404. || (Confusion && !rn2(3))) { 405. *sptmp = '!' + rn2(93); /* ASCII-code only */ 406. } 407. } 408. 409. switch(type) { 410. case DUST: 411. case BURN: 412. if(len > 15) { 413. multi = -(len/10); 414. nomovemsg = "You finished writing."; 415. } 416. break; 417. case ENGRAVE: 418. #ifdef MARKER 419. case MARK: 420. { int len2; 421. 422. if(type == ENGRAVE) 423. len2 = (otmp->spe + 3) * 2 + 1; 424. else 425. len2 = (otmp->spe) * 2; 426. nomovemsg = "You finished writing."; 427. if(type != MARK) 428. #else 429. { int len2 = (otmp->spe + 3) * 2 + 1; 430. #endif 431. nomovemsg = "You finished engraving."; 432. if(otmp->olet != WAND_SYM) { 433. if(otmp->olet == WEAPON_SYM) 434. pline("Your %s dull.", 435. aobjnam(otmp, "get")); 436. if(len2 < len) { 437. len = len2; 438. sp[len] = 0; 439. if(type == ENGRAVE) { 440. otmp->spe = -3; 441. } else { 442. pline("Your marker dries out!"); 443. otmp->spe = 0; 444. } 445. /* next line added by GAN 10/20/86 */ 446. pline("You only write \"%s\".", sp); 447. nomovemsg = "You cannot write more."; 448. } else 449. otmp->spe -= len/2; 450. #ifdef MARKER 451. if(type == MARK) 452. multi = -(len/10); 453. else 454. #endif 455. multi = -len; 456. } else 457. multi = -(len/10); 458. } 459. break; 460. } 461. if(oep) len += strlen(oep->engr_txt) + spct; 462. ep = (struct engr *) alloc((unsigned)(sizeof(struct engr) + len + 1)); 463. ep->nxt_engr = head_engr; 464. head_engr = ep; 465. ep->engr_x = u.ux; 466. ep->engr_y = u.uy; 467. sp = (char *)(ep + 1); /* (char *)ep + sizeof(struct engr) */ 468. ep->engr_txt = sp; 469. if(oep) { 470. (void) strcpy(sp, oep->engr_txt); 471. (void) strcat(sp, buf); 472. del_engr(oep); 473. } else 474. (void) strcpy(sp, buf); 475. ep->engr_lth = len+1; 476. ep->engr_type = type; 477. ep->engr_time = moves-multi; 478. 479. /* kludge to protect pline against excessively long texts */ 480. if(len > BUFSZ-20) sp[BUFSZ-20] = 0; 481. 482. /* cute messages for odd wands */ 483. switch(otmp->otyp) { 484. case WAN_SLOW_MONSTER: 485. pline("The bugs on the ground slow down!"); 486. break; 487. case WAN_SPEED_MONSTER: 488. pline("The bugs on the ground speed up!"); 489. break; 490. case WAN_MAGIC_MISSILE: 491. pline("The ground is riddled by bullet holes!"); 492. break; 493. case WAN_SLEEP: 494. case WAN_DEATH: /* can't tell sleep from death - Eric Backus */ 495. pline("The bugs on the ground stop moving!"); 496. break; 497. case WAN_COLD: 498. pline("A few ice cubes drop from your %s.",xname(otmp)); 499. break; 500. case WAN_STRIKING: 501. pline("The %s unsuccessfully fights your attempt to write!",xname(otmp)); 502. } 503. 504. return(1); 505. } 506. 507. save_engravings(fd) int fd; { 508. register struct engr *ep = head_engr; 509. while(ep) { 510. if(!ep->engr_lth || !ep->engr_txt[0]){ 511. ep = ep->nxt_engr; 512. continue; 513. } 514. bwrite(fd, (char *) & (ep->engr_lth), sizeof(ep->engr_lth)); 515. bwrite(fd, (char *) ep, sizeof(struct engr) + ep->engr_lth); 516. ep = ep->nxt_engr; 517. } 518. bwrite(fd, (char *) nul, sizeof(unsigned)); 519. #ifdef DGK 520. if (!count_only) 521. #endif 522. head_engr = 0; 523. } 524. 525. rest_engravings(fd) int fd; { 526. register struct engr *ep; 527. unsigned lth; 528. head_engr = 0; 529. while(1) { 530. mread(fd, (char *) <h, sizeof(unsigned)); 531. if(lth == 0) return; 532. ep = (struct engr *) alloc(sizeof(struct engr) + lth); 533. mread(fd, (char *) ep, sizeof(struct engr) + lth); 534. ep->nxt_engr = head_engr; 535. ep->engr_txt = (char *) (ep + 1); /* Andreas Bormann */ 536. head_engr = ep; 537. } 538. } 539. 540. del_engr(ep) register struct engr *ep; { 541. register struct engr *ept; 542. if(ep == head_engr) 543. head_engr = ep->nxt_engr; 544. else { 545. for(ept = head_engr; ept; ept = ept->nxt_engr) { 546. if(ept->nxt_engr == ep) { 547. ept->nxt_engr = ep->nxt_engr; 548. goto fnd; 549. } 550. } 551. impossible("Error in del_engr?"); 552. return; 553. fnd: ; 554. } 555. free((char *) ep); 556. }
|