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