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 8extern const char *hu_stat[]; /* defined in eat.c */ 9 10const char * const enc_stat[] = { 11 "", 12 "Burdened", 13 "Stressed", 14 "Strained", 15 "Overtaxed", 16 "Overloaded" 17}; 18 19STATIC_DCL void NDECL(bot1); 20STATIC_DCL void NDECL(bot2); 21#endif /* OVL0 */ 22 23/* MAXCO must hold longest uncompressed status line, and must be larger 24 * than COLNO 25 * 26 * longest practical second status line at the moment is 27 * Astral Plane $:12345 HP:700(700) Pw:111(111) AC:-127 Xp:30/123456789 28 * T:123456 Satiated Conf FoodPois Ill Blind Stun Hallu Overloaded 29 * -- or somewhat over 130 characters 30 */ 31#if COLNO <= 140 32#define MAXCO 160 33#else 34#define MAXCO (COLNO+20) 35#endif 36 37#ifndef OVLB 38STATIC_DCL int mrank_sz; 39#else /* OVLB */ 40STATIC_OVL NEARDATA int mrank_sz = 0; /* loaded by max_rank_sz (from u_init) */ 41#endif /* OVLB */ 42 43STATIC_DCL const char *NDECL(rank); 44 45#ifdef OVL1 46 47/* convert experience level (1..30) to rank index (0..8) */ 48int 49xlev_to_rank(xlev) 50int xlev; 51{ 52 return (xlev <= 2) ? 0 : (xlev <= 30) ? ((xlev + 2) / 4) : 8; 53} 54 55#if 0 /* not currently needed */ 56/* convert rank index (0..8) to experience level (1..30) */ 57int 58rank_to_xlev(rank) 59int rank; 60{ 61 return (rank <= 0) ? 1 : (rank <= 8) ? ((rank * 4) - 2) : 30; 62} 63#endif 64 65const char * 66rank_of(lev, monnum, female) 67 int lev; 68 short monnum; 69 boolean female; 70{ 71 register struct Role *role; 72 register int i; 73 74 75 /* Find the role */ 76 for (role = (struct Role *) roles; role->name.m; role++) 77 if (monnum == role->malenum || monnum == role->femalenum) 78 break; 79 if (!role->name.m) 80 role = &urole; 81 82 /* Find the rank */ 83 for (i = xlev_to_rank((int)lev); i >= 0; i--) { 84 if (female && role->rank[i].f) return (role->rank[i].f); 85 if (role->rank[i].m) return (role->rank[i].m); 86 } 87 88 /* Try the role name, instead */ 89 if (female && role->name.f) return (role->name.f); 90 else if (role->name.m) return (role->name.m); 91 return ("Player"); 92} 93 94 95STATIC_OVL const char * 96rank() 97{ 98 return(rank_of(u.ulevel, Role_switch, flags.female)); 99} 100 101int 102title_to_mon(str, rank_indx, title_length) 103const char *str; 104int *rank_indx, *title_length; 105{ 106 register int i, j; 107 108 109 /* Loop through each of the roles */ 110 for (i = 0; roles[i].name.m; i++) 111 for (j = 0; j < 9; j++) { 112 if (roles[i].rank[j].m && !strncmpi(str, 113 roles[i].rank[j].m, strlen(roles[i].rank[j].m))) { 114 if (rank_indx) *rank_indx = j; 115 if (title_length) *title_length = strlen(roles[i].rank[j].m); 116 return roles[i].malenum; 117 } 118 if (roles[i].rank[j].f && !strncmpi(str, 119 roles[i].rank[j].f, strlen(roles[i].rank[j].f))) { 120 if (rank_indx) *rank_indx = j; 121 if (title_length) *title_length = strlen(roles[i].rank[j].f); 122 return ((roles[i].femalenum != NON_PM) ? 123 roles[i].femalenum : roles[i].malenum); 124 } 125 } 126 return NON_PM; 127} 128 129#endif /* OVL1 */ 130#ifdef OVLB 131 132void 133max_rank_sz() 134{ 135 register int i, r, maxr = 0; 136 for (i = 0; i < 9; i++) { 137 if (urole.rank[i].m && (r = strlen(urole.rank[i].m)) > maxr) maxr = r; 138 if (urole.rank[i].f && (r = strlen(urole.rank[i].f)) > maxr) maxr = r; 139 } 140 mrank_sz = maxr; 141 return; 142} 143 144#endif /* OVLB */ 145#ifdef OVL0 146 147#ifdef SCORE_ON_BOTL 148long 149botl_score() 150{ 151 int deepest = deepest_lev_reached(FALSE); 152#ifndef GOLDOBJ 153 long ugold = u.ugold + hidden_gold(); 154 155 if ((ugold -= u.ugold0) < 0L) ugold = 0L; 156 return ugold + u.urexp + (long)(50 * (deepest - 1)) 157#else 158 long umoney = money_cnt(invent) + hidden_gold(); 159 160 if ((umoney -= u.umoney0) < 0L) umoney = 0L; 161 return umoney + u.urexp + (long)(50 * (deepest - 1)) 162#endif 163 + (long)(deepest > 30 ? 10000 : 164 deepest > 20 ? 1000*(deepest - 20) : 0); 165} 166#endif 167 168STATIC_OVL void 169bot1() 170{ 171 char newbot1[MAXCO]; 172 register char *nb; 173 register int i,j; 174 175 Strcpy(newbot1, plname); 176 if('a' <= newbot1[0] && newbot1[0] <= 'z') newbot1[0] += 'A'-'a'; 177 newbot1[10] = 0; 178 Sprintf(nb = eos(newbot1)," the "); 179 180 if (Upolyd) { 181 char mbot[BUFSZ]; 182 int k = 0; 183 184 Strcpy(mbot, mons[u.umonnum].mname); 185 while(mbot[k] != 0) { 186 if ((k == 0 || (k > 0 && mbot[k-1] == ' ')) && 187 'a' <= mbot[k] && mbot[k] <= 'z') 188 mbot[k] += 'A' - 'a'; 189 k++; 190 } 191 Sprintf(nb = eos(nb), mbot); 192 } else 193 Sprintf(nb = eos(nb), rank()); 194 195 Sprintf(nb = eos(nb)," "); 196 i = mrank_sz + 15; 197 j = (nb + 2) - newbot1; /* aka strlen(newbot1) but less computation */ 198 if((i - j) > 0) 199 Sprintf(nb = eos(nb),"%*s", i-j, " "); /* pad with spaces */ 200 if (ACURR(A_STR) > 18) { 201 if (ACURR(A_STR) > STR18(100)) 202 Sprintf(nb = eos(nb),"St:%2d ",ACURR(A_STR)-100); 203 else if (ACURR(A_STR) < STR18(100)) 204 Sprintf(nb = eos(nb), "St:18/%02d ",ACURR(A_STR)-18); 205 else 206 Sprintf(nb = eos(nb),"St:18/** "); 207 } else 208 Sprintf(nb = eos(nb), "St:%-1d ",ACURR(A_STR)); 209 Sprintf(nb = eos(nb), 210 "Dx:%-1d Co:%-1d In:%-1d Wi:%-1d Ch:%-1d", 211 ACURR(A_DEX), ACURR(A_CON), ACURR(A_INT), ACURR(A_WIS), ACURR(A_CHA)); 212 Sprintf(nb = eos(nb), (u.ualign.type == A_CHAOTIC) ? " Chaotic" : 213 (u.ualign.type == A_NEUTRAL) ? " Neutral" : " Lawful"); 214#ifdef SCORE_ON_BOTL 215 if (flags.showscore) 216 Sprintf(nb = eos(nb), " S:%ld", botl_score()); 217#endif 218 curs(WIN_STATUS, 1, 0); 219 putstr(WIN_STATUS, 0, newbot1); 220} 221 222/* provide the name of the current level for display by various ports */ 223int 224describe_level(buf) 225char *buf; 226{ 227 int ret = 1; 228 229 /* TODO: Add in dungeon name */ 230 if (Is_knox(&u.uz)) 231 Sprintf(buf, "%s ", dungeons[u.uz.dnum].dname); 232 else if (In_quest(&u.uz)) 233 Sprintf(buf, "Home %d ", dunlev(&u.uz)); 234 else if (In_endgame(&u.uz)) 235 Sprintf(buf, 236 Is_astralevel(&u.uz) ? "Astral Plane " : "End Game "); 237 else { 238 /* ports with more room may expand this one */ 239 Sprintf(buf, "Dlvl:%-2d ", depth(&u.uz)); 240 ret = 0; 241 } 242 return ret; 243} 244 245STATIC_OVL void 246bot2() 247{ 248 char newbot2[MAXCO]; 249 register char *nb; 250 int hp, hpmax; 251 int cap = near_capacity(); 252 253 hp = Upolyd ? u.mh : u.uhp; 254 hpmax = Upolyd ? u.mhmax : u.uhpmax; 255 256 if(hp < 0) hp = 0; 257 (void) describe_level(newbot2); 258 Sprintf(nb = eos(newbot2), 259 "%c:%-2ld HP:%d(%d) Pw:%d(%d) AC:%-2d", oc_syms[COIN_CLASS], 260#ifndef GOLDOBJ 261 u.ugold, 262#else 263 money_cnt(invent), 264#endif 265 hp, hpmax, u.uen, u.uenmax, u.uac); 266 267 if (Upolyd) 268 Sprintf(nb = eos(nb), " HD:%d", mons[u.umonnum].mlevel); 269#ifdef EXP_ON_BOTL 270 else if(flags.showexp) 271 Sprintf(nb = eos(nb), " Xp:%u/%-1ld", u.ulevel,u.uexp); 272#endif 273 else 274 Sprintf(nb = eos(nb), " Exp:%u", u.ulevel); 275 276 if(flags.time) 277 Sprintf(nb = eos(nb), " T:%ld", moves); 278 if(strcmp(hu_stat[u.uhs], " ")) { 279 Sprintf(nb = eos(nb), " "); 280 Strcat(newbot2, hu_stat[u.uhs]); 281 } 282 if(Confusion) Sprintf(nb = eos(nb), " Conf"); 283 if(Sick) { 284 if (u.usick_type & SICK_VOMITABLE) 285 Sprintf(nb = eos(nb), " FoodPois"); 286 if (u.usick_type & SICK_NONVOMITABLE) 287 Sprintf(nb = eos(nb), " Ill"); 288 } 289 if(Blind) Sprintf(nb = eos(nb), " Blind"); 290 if(Stunned) Sprintf(nb = eos(nb), " Stun"); 291 if(Hallucination) Sprintf(nb = eos(nb), " Hallu"); 292 if(Slimed) Sprintf(nb = eos(nb), " Slime"); 293 if(cap > UNENCUMBERED) 294 Sprintf(nb = eos(nb), " %s", enc_stat[cap]); 295 curs(WIN_STATUS, 1, 1); 296 putstr(WIN_STATUS, 0, newbot2); 297} 298 299void 300bot() 301{ 302 bot1(); 303 bot2(); 304 flags.botl = flags.botlx = 0; 305} 306 307#endif /* OVL0 */ 308 309/*botl.c*/ 310