Below is the full text to botl.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/botl.c#line123]], for example.
The latest source code for vanilla NetHack is at Source code.
The NetHack General Public License applies to screenshots, source code and other content from NetHack. |
1. /* SCCS Id: @(#)botl.c 3.4 1996/07/15 */ 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. #ifdef OVL0 8. extern const char *hu_stat[]; /* defined in eat.c */ 9. 10. const char *hu_abbrev_stat[] = { /* must be kept consistent with eat.c */ 11. "Sat", 12. "", 13. "Hun", 14. "Wea", 15. "Ftg", 16. "Ftd", 17. "Sta" 18. }; 19. 20. const char * const enc_stat[] = { 21. "", 22. "Burdened", 23. "Stressed", 24. "Strained", 25. "Overtaxed", 26. "Overloaded" 27. }; 28. 29. const char *enc_abbrev_stat[] = { 30. "", 31. "Brd", 32. "Ssd", 33. "Snd", 34. "Otd", 35. "Old" 36. }; 37. 38. STATIC_DCL void NDECL(bot1); 39. STATIC_DCL void NDECL(bot2); 40. #ifdef ALLEG_FX 41. STATIC_DCL void FDECL(set_botl_warn, (int)); 42. #endif 43. #endif /* OVL0 */ 44. 45. /* MAXCO must hold longest uncompressed status line, and must be larger 46. * than COLNO 47. * 48. * longest practical second status line at the moment is 49. * Astral Plane $:12345 HP:700(700) Pw:111(111) AC:-127 Xp:30/123456789 50. * Wt:5000/1000 T:123456 Satiated Lev Conf FoodPois Ill Blind Stun Hallu 51. * Slime Held Overloaded 52. * -- or somewhat over 160 characters 53. */ 54. #if COLNO <= 170 55. #define MAXCO 190 56. #else 57. #define MAXCO (COLNO+20) 58. #endif 59. 60. #ifndef OVLB 61. STATIC_DCL int mrank_sz; 62. #else /* OVLB */ 63. STATIC_OVL NEARDATA int mrank_sz = 0; /* loaded by max_rank_sz (from u_init) */ 64. #endif /* OVLB */ 65. 66. STATIC_DCL const char *NDECL(rank); 67. 68. #ifdef OVL1 69. 70. #ifdef ALLEG_FX 71. static int botl_warn = 0; 72. 73. static void 74. set_botl_warn(level) 75. int level; 76. { 77. botl_warn = level; 78. flags.botl = 1; 79. } 80. #endif 81. 82. /* convert experience level (1..30) to rank index (0..8) */ 83. int 84. xlev_to_rank(xlev) 85. int xlev; 86. { 87. return (xlev <= 2) ? 0 : (xlev <= 30) ? ((xlev + 2) / 4) : 8; 88. } 89. 90. #if 0 /* not currently needed */ 91. /* convert rank index (0..8) to experience level (1..30) */ 92. int 93. rank_to_xlev(rank) 94. int rank; 95. { 96. return (rank <= 0) ? 1 : (rank <= 8) ? ((rank * 4) - 2) : 30; 97. } 98. #endif 99. 100. const char * 101. rank_of(lev, monnum, female) 102. int lev; 103. short monnum; 104. boolean female; 105. { 106. register struct Role *role; 107. register int i; 108. 109. 110. /* Find the role */ 111. for (role = (struct Role *) roles; role->name.m; role++) 112. if (monnum == role->malenum || monnum == role->femalenum) 113. break; 114. if (!role->name.m) 115. role = &urole; 116. 117. /* Find the rank */ 118. for (i = xlev_to_rank((int)lev); i >= 0; i--) { 119. if (female && role->rank[i].f) return (role->rank[i].f); 120. if (role->rank[i].m) return (role->rank[i].m); 121. } 122. 123. /* Try the role name, instead */ 124. if (female && role->name.f) return (role->name.f); 125. else if (role->name.m) return (role->name.m); 126. return ("Player"); 127. } 128. 129. 130. STATIC_OVL const char * 131. rank() 132. { 133. return(rank_of(u.ulevel, Role_switch, flags.female)); 134. } 135. 136. int 137. title_to_mon(str, rank_indx, title_length) 138. const char *str; 139. int *rank_indx, *title_length; 140. { 141. register int i, j; 142. 143. 144. /* Loop through each of the roles */ 145. for (i = 0; roles[i].name.m; i++) 146. for (j = 0; j < 9; j++) { 147. if (roles[i].rank[j].m && !strncmpi(str, 148. roles[i].rank[j].m, strlen(roles[i].rank[j].m))) { 149. if (rank_indx) *rank_indx = j; 150. if (title_length) *title_length = strlen(roles[i].rank[j].m); 151. return roles[i].malenum; 152. } 153. if (roles[i].rank[j].f && !strncmpi(str, 154. roles[i].rank[j].f, strlen(roles[i].rank[j].f))) { 155. if (rank_indx) *rank_indx = j; 156. if (title_length) *title_length = strlen(roles[i].rank[j].f); 157. return ((roles[i].femalenum != NON_PM) ? 158. roles[i].femalenum : roles[i].malenum); 159. } 160. } 161. return NON_PM; 162. } 163. 164. #endif /* OVL1 */ 165. #ifdef OVLB 166. 167. void 168. max_rank_sz() 169. { 170. register int i, r, maxr = 0; 171. 172. 173. for (i = 0; i < 9; i++) { 174. if (urole.rank[i].m && (r = strlen(urole.rank[i].m)) > maxr) maxr = r; 175. if (urole.rank[i].f && (r = strlen(urole.rank[i].f)) > maxr) maxr = r; 176. } 177. mrank_sz = maxr; 178. return; 179. } 180. 181. #endif /* OVLB */ 182. #ifdef OVL0 183. 184. #ifdef SCORE_ON_BOTL 185. long 186. botl_score() 187. { 188. int deepest = deepest_lev_reached(FALSE); 189. #ifndef GOLDOBJ 190. long ugold = u.ugold + hidden_gold(); 191. 192. if ((ugold -= u.ugold0) < 0L) ugold = 0L; 193. return ugold + u.urexp + (long)(50 * (deepest - 1)) 194. #else 195. long umoney = money_cnt(invent) + hidden_gold(); 196. 197. if ((umoney -= u.umoney0) < 0L) umoney = 0L; 198. return umoney + u.urexp + (long)(50 * (deepest - 1)) 199. #endif 200. + (long)(deepest > 30 ? 10000 : 201. deepest > 20 ? 1000*(deepest - 20) : 0); 202. } 203. #endif 204. 205. static char * 206. botl_player() 207. { 208. static char player[MAXCO]; 209. register char *nb; 210. char mbot[MAXCO - 15]; 211. int k = 0; 212. 213. Strcpy(player, plname); 214. if ('a' <= player[0] && player[0] <= 'z') player[0] += 'A'-'a'; 215. player[10] = 0; 216. Sprintf(nb = eos(player)," the "); 217. 218. if (Upolyd) { 219. (void) strncpy(mbot, mons[u.umonnum].mname, SIZE(mbot) - 1); 220. mbot[SIZE(mbot) - 1] = 0; 221. while(mbot[k] != 0) { 222. if ((k == 0 || (k > 0 && mbot[k-1] == ' ')) && 223. 'a' <= mbot[k] && mbot[k] <= 'z') 224. mbot[k] += 'A' - 'a'; 225. k++; 226. } 227. Sprintf(eos(nb), mbot); 228. } else 229. Sprintf(eos(nb), rank()); 230. return player; 231. } 232. 233. static char * 234. botl_strength() 235. { 236. static char strength[6]; 237. if (ACURR(A_STR) > 18) { 238. if (ACURR(A_STR) > STR18(100)) 239. Sprintf(strength, "%2d", ACURR(A_STR)-100); 240. else if (ACURR(A_STR) < STR18(100)) 241. Sprintf(strength, "18/%02d", ACURR(A_STR)-18); 242. else 243. Sprintf(strength, "18/**"); 244. } else 245. Sprintf(strength, "%-1d", ACURR(A_STR)); 246. return strength; 247. } 248. 249. STATIC_OVL void 250. bot1() 251. { 252. char newbot1[MAXCO]; 253. register char *nb; 254. register int i,j; 255. 256. Strcpy(newbot1, botl_player()); 257. Sprintf(nb = eos(newbot1)," "); 258. i = mrank_sz + 15; 259. j = (nb + 2) - newbot1; /* aka strlen(newbot1) but less computation */ 260. if((i - j) > 0) 261. Sprintf(nb = eos(nb),"%*s", i-j, " "); /* pad with spaces */ 262. 263. Sprintf(nb = eos(nb), "St:%s ", botl_strength()); 264. Sprintf(nb = eos(nb), 265. "Dx:%-1d Co:%-1d In:%-1d Wi:%-1d Ch:%-1d", 266. ACURR(A_DEX), ACURR(A_CON), ACURR(A_INT), ACURR(A_WIS), ACURR(A_CHA)); 267. Sprintf(nb = eos(nb), (u.ualign.type == A_CHAOTIC) ? " Chaotic" : 268. (u.ualign.type == A_NEUTRAL) ? " Neutral" : " Lawful"); 269. #ifdef SCORE_ON_BOTL 270. if (flags.showscore) 271. Sprintf(nb = eos(nb), " S:%ld", botl_score()); 272. #endif 273. curs(WIN_STATUS, 1, 0); 274. putstr(WIN_STATUS, 0, newbot1); 275. } 276. 277. /* provide the name of the current level for display by various ports */ 278. int 279. describe_level(buf, verbose) 280. char *buf; 281. int verbose; 282. { 283. int ret = 1; 284. 285. /* TODO: Add in dungeon name */ 286. if (Is_knox(&u.uz)) 287. Sprintf(buf, "%s ", dungeons[u.uz.dnum].dname); 288. else if (In_quest(&u.uz)) 289. Sprintf(buf, "Home %d ", dunlev(&u.uz)); 290. else if (In_endgame(&u.uz)) 291. Sprintf(buf, 292. Is_astralevel(&u.uz) ? "Astral Plane " : "End Game "); 293. else { 294. if (verbose) 295. Sprintf(buf, "%s, level %d ", 296. dungeons[u.uz.dnum].dname, depth(&u.uz)); 297. else 298. Sprintf(buf, "Dlvl:%-2d ", depth(&u.uz)); 299. ret = 0; 300. } 301. return ret; 302. } 303. 304. /* [ALI] Line 2 abbreviation levels: 305. * 0 - No abbreviation 306. * 1 - Omit gold 307. * 2 - Abbreviated status tags 308. * 3 - Disable show options 309. * 4 - Omit dungeon level 310. * 311. * We omit gold first since the '$' command is always available. 312. * 313. * While the abbreviated status tags are very difficult to interpret, we use 314. * these before disabling the show options on the basis that the user always 315. * has the choice of turning the show options off if that would be preferable. 316. * 317. * Last to go is the dungeon level on the basis that there is no way of 318. * finding this information other than via the status line. 319. */ 320. 321. static int bot2_abbrev = 0; /* Line 2 abbreviation level (max 4) */ 322. 323. STATIC_OVL void 324. bot2str(char *newbot2) 325. { 326. register char *nb; 327. int hp, hpmax; 328. int cap = near_capacity(); 329. #ifdef ALLEG_FX 330. int w; 331. #endif 332. 333. hp = Upolyd ? u.mh : u.uhp; 334. hpmax = Upolyd ? u.mhmax : u.uhpmax; 335. 336. if(hp < 0) hp = 0; 337. if (bot2_abbrev < 4) 338. (void) describe_level(newbot2, FALSE); 339. else 340. newbot2[0] = '\0'; 341. if (bot2_abbrev < 1) 342. Sprintf(nb = eos(newbot2), "%c:%-2ld ", 343. oc_syms[COIN_CLASS], 344. #ifndef GOLDOBJ 345. u.ugold 346. #else 347. money_cnt(invent) 348. #endif 349. ); 350. else 351. nb = newbot2; 352. Sprintf(nb = eos(nb), "HP:%d(%d) Pw:%d(%d) AC:%-2d", 353. hp, hpmax, u.uen, u.uenmax, u.uac); 354. 355. if (Upolyd) 356. Sprintf(nb = eos(nb), " HD:%d", ((u.ulycn == u.umonnum) ? 357. u.ulevel : mons[u.umonnum].mlevel)); 358. #ifdef EXP_ON_BOTL 359. else if(flags.showexp && bot2_abbrev < 3) 360. Sprintf(nb = eos(nb), " Xp:%u/%-1ld", u.ulevel,u.uexp); 361. #endif 362. else 363. Sprintf(nb = eos(nb), " Exp:%u", u.ulevel); 364. 365. #ifdef SHOW_WEIGHT 366. if (flags.showweight && bot2_abbrev < 3) 367. Sprintf(nb = eos(nb), " Wt:%ld/%ld", (long)(inv_weight()+weight_cap()), 368. (long)weight_cap()); 369. #endif 370. 371. if(flags.time && bot2_abbrev < 3) 372. Sprintf(nb = eos(nb), " T:%ld ", moves); 373. 374. #ifdef ALLEG_FX 375. if(iflags.usealleg && botl_warn && !Hallucination) 376. { 377. Sprintf(nb = eos(nb), " "); 378. for(w = 0; w < botl_warn; w++) 379. Sprintf(nb = eos(nb), "!"); 380. } 381. #endif 382. 383. if (bot2_abbrev >= 2) { 384. if (hu_abbrev_stat[u.uhs][0]!='\0') { 385. Sprintf(nb = eos(nb), " "); 386. Strcat(newbot2, hu_abbrev_stat[u.uhs]); 387. } 388. } 389. else if(strcmp(hu_stat[u.uhs], " ")) { 390. Sprintf(nb = eos(nb), " "); 391. Strcat(newbot2, hu_stat[u.uhs]); 392. } 393. 394. /* WAC further Up 395. #ifdef SCORE_ON_BOTL 396. if (flags.showscore) 397. Sprintf(nb,"%c:%-2ld Score:%ld", oc_syms[COIN_CLASS], 398. u.ugold, botl_score()); 399. #endif 400. */ 401. /* KMH -- changed to Lev */ 402. if (Levitation) Sprintf(nb = eos(nb), " Lev"); 403. if(Confusion) 404. Sprintf(nb = eos(nb), bot2_abbrev >= 2 ? " Cnf" : " Conf"); 405. if(Sick) { 406. if (u.usick_type & SICK_VOMITABLE) 407. Sprintf(nb = eos(nb), 408. bot2_abbrev >= 2 ? " FPs" : " FoodPois"); 409. if (u.usick_type & SICK_NONVOMITABLE) 410. Sprintf(nb = eos(nb), " Ill"); 411. } 412. 413. if(Blind) 414. Sprintf(nb = eos(nb), bot2_abbrev >= 2 ? " Bnd" : " Blind"); 415. if(Stunned) 416. Sprintf(nb = eos(nb), bot2_abbrev >= 2 ? " Stn" : " Stun"); 417. if(Hallucination) 418. Sprintf(nb = eos(nb), bot2_abbrev >= 2 ? " Hal" : " Hallu"); 419. if(Slimed) 420. Sprintf(nb = eos(nb), bot2_abbrev >= 2 ? " Slm" : " Slime"); 421. if(u.ustuck && !u.uswallow && !sticks(youmonst.data)) 422. Sprintf(nb = eos(nb), " Held"); 423. if(cap > UNENCUMBERED) 424. Sprintf(nb = eos(nb), " %s", 425. bot2_abbrev >= 2 ? enc_abbrev_stat[cap] : enc_stat[cap]); 426. } 427. 428. STATIC_OVL void 429. bot2() 430. { 431. char newbot2[MAXCO]; 432. 433. bot2str(newbot2); 434. curs(WIN_STATUS, 1, 1); 435. 436. putstr(WIN_STATUS, 0, newbot2); 437. return; 438. } 439. 440. /* WAC -- Shorten bot1 to fit in len spaces. 441. * Not currently used 442. * Longest string past Str: is 443. * ". Str:18/99 Dx:11 Co:13 In:12 Wi:14 Ch:14 Neutral" or 49 Chars long. 444. */ 445. #if 0 446. const char* 447. shorten_bot1(str, len) 448. const char *str; 449. int len; 450. { 451. static char cbuf[BUFSZ]; 452. 453. register const char *bp0 = str; 454. register char *bp1 = cbuf; 455. int k = 0; 456. 457. do { 458. *bp1++ = *bp0; 459. k++; 460. } while(*bp0++ && k < (len - 49)); 461. 462. cbuf[k] = '.'; 463. bp1++; 464. 465. bp0 = index(str, ':') - 3; 466. do { 467. *bp1++ = *bp0; 468. } while(*bp0++); 469. return cbuf; 470. } 471. #endif /* 0 */ 472. 473. /* ALI -- Shorten bot2 to fit in len spaces. 474. * Currently only used by tty port 475. * After the forth attempt the longest practical bot2 becomes: 476. * HP:700(700) Pw:111(111) AC:-127 Exp:30 477. * Sat Lev Cnf FPs Ill Bnd Stn Hal Slm Old 478. * -- or just under 80 characters 479. */ 480. #ifdef TTY_GRAPHICS 481. const char* 482. shorten_bot2(str, len) 483. const char *str; 484. unsigned int len; 485. { 486. static char cbuf[MAXCO]; 487. for(bot2_abbrev = 1; bot2_abbrev <= 4; bot2_abbrev++) { 488. bot2str(cbuf); 489. if (strlen(cbuf) <= len) 490. break; 491. } 492. if (bot2_abbrev > 4) 493. cbuf[len] = '\0'; /* If all else fails, truncate the line */ 494. bot2_abbrev = 0; 495. return cbuf; 496. } 497. #endif /* TTY_GRAPHICS */ 498. 499. static void (*raw_handler)(); 500. 501. static void bot_raw(reconfig) 502. boolean reconfig; 503. { 504. const char *botl_raw_values[24], **rv = botl_raw_values; 505. char dex[3], con[3], itl[3], wis[3], cha[3], score[21]; 506. int uhp; 507. char dlevel[BUFSZ]; 508. char hp[21], hpmax[21], pw[21], pwmax[21], gold[21], ac[21], elevel[21]; 509. char expr[21], iweight[21], capacity[21], flgs[21], tim[21]; 510. *rv++ = reconfig ? "player" : botl_player(); 511. *rv++ = reconfig ? "strength" : botl_strength(); 512. *rv++ = reconfig ? "dexterity" : (Sprintf(dex, "%d", ACURR(A_DEX)), dex); 513. *rv++ = reconfig ? "constitution" : (Sprintf(con, "%d", ACURR(A_CON)), con); 514. *rv++ = reconfig ? "intelligence" : (Sprintf(itl, "%d", ACURR(A_INT)), itl); 515. *rv++ = reconfig ? "wisdom" : (Sprintf(wis, "%d", ACURR(A_WIS)), wis); 516. *rv++ = reconfig ? "charisma" : (Sprintf(cha, "%d", ACURR(A_CHA)), cha); 517. *rv++ = reconfig ? "alignment" : u.ualign.type == A_CHAOTIC ? "Chaotic" : 518. u.ualign.type == A_NEUTRAL ? "Neutral" : "Lawful"; 519. #ifdef SCORE_ON_BOTL 520. if (flags.showscore) 521. *rv++ = reconfig ? "score" : 522. (Sprintf(score, "%ld", botl_score()), score); 523. #endif 524. uhp = Upolyd ? u.mh : u.uhp; 525. if (uhp < 0) uhp = 0; 526. (void) describe_level(dlevel, TRUE); 527. eos(dlevel)[-1] = 0; 528. *rv++ = reconfig ? "dlevel" : dlevel; 529. *rv++ = reconfig ? "gold" : (Sprintf(gold, "%ld", 530. #ifndef GOLDOBJ 531. u.ugold 532. #else 533. money_cnt(invent) 534. #endif 535. ), gold); 536. *rv++ = reconfig ? "hp" : (Sprintf(hp, "%d", uhp), hp); 537. *rv++ = reconfig ? "hpmax" : 538. (Sprintf(hpmax, "%d", Upolyd ? u.mhmax : u.uhpmax), hpmax); 539. *rv++ = reconfig ? "pw" : (Sprintf(pw, "%d", u.uen), pw); 540. *rv++ = reconfig ? "pwmax" : (Sprintf(pwmax, "%d", u.uenmax), pwmax); 541. *rv++ = reconfig ? "ac" : (Sprintf(ac, "%d", u.uac), ac); 542. Sprintf(elevel, "%u", 543. Upolyd && u.ulycn != u.umonnum ? mons[u.umonnum].mlevel : u.ulevel); 544. *rv++ = reconfig ? (Upolyd ? "hitdice" : "elevel") : elevel; 545. #ifdef EXP_ON_BOTL 546. if (flags.showexp) 547. *rv++ = reconfig ? "experience" : (Sprintf(expr, "%ld", u.uexp), expr); 548. #endif 549. #ifdef SHOW_WEIGHT 550. if (flags.showweight) { 551. *rv++ = reconfig ? "weight" : (Sprintf(iweight, 552. "%ld", (long)(inv_weight() + weight_cap())), iweight); 553. *rv++ = reconfig ? "capacity" : (Sprintf(capacity, 554. "%ld", (long)weight_cap()), capacity); 555. } 556. #endif 557. if (flags.time) 558. *rv++ = reconfig ? "time" : (Sprintf(tim, "%ld", moves), tim); 559. *rv++ = reconfig ? "hunger" : strcmp(hu_stat[u.uhs], " ") ? 560. hu_stat[u.uhs] : ""; 561. *rv++ = reconfig ? "encumberance" : enc_stat[near_capacity()]; 562. *rv++ = reconfig ? "flags" : (Sprintf(flgs, "%lX", 563. (Levitation ? RAW_STAT_LEVITATION : 0) | 564. (Confusion ? RAW_STAT_CONFUSION : 0) | 565. (Sick && (u.usick_type & SICK_VOMITABLE) ? RAW_STAT_FOODPOIS : 0) | 566. (Sick && (u.usick_type & SICK_NONVOMITABLE) ? RAW_STAT_ILL : 0) | 567. (Blind ? RAW_STAT_BLIND : 0) | 568. (Stunned ? RAW_STAT_STUNNED : 0) | 569. (Hallucination ? RAW_STAT_HALLUCINATION : 0) | 570. (Slimed ? RAW_STAT_SLIMED : 0)), flgs); 571. (*raw_handler)(reconfig, rv - botl_raw_values, botl_raw_values); 572. } 573. 574. void bot_reconfig() 575. { 576. if (raw_handler) 577. bot_raw(TRUE); 578. flags.botl = 1; 579. } 580. 581. void 582. bot_set_handler(handler) 583. void (*handler)(); 584. { 585. raw_handler = handler; 586. bot_reconfig(); 587. } 588. 589. void 590. bot() 591. { 592. /* 593. * ALI: Cope with the fact that u_init may not have been 594. * called yet. This happens if the player selection menus 595. * are long enough to overwite the status line. In this 596. * case we will be called when the menu is removed while 597. * youmonst.data is still NULL. 598. */ 599. if (!youmonst.data) 600. return; 601. if (raw_handler) 602. bot_raw(FALSE); 603. else { 604. bot1(); 605. bot2(); 606. } 607. flags.botl = flags.botlx = 0; 608. } 609. 610. #endif /* OVL0 */ 611. 612. /*botl.c*/