Source:SLASH'EM 0.0.7E7F2/botl.c
Jump to navigation
Jump to search
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.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
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*/