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