Commit | Line | Data |
---|---|---|
15637ed4 RG |
1 | /* display.c Larn is copyrighted 1986 by Noah Morgan. */ |
2 | #include "header.h" | |
3 | #define makecode(_a,_b,_c) (((_a)<<16) + ((_b)<<8) + (_c)) | |
4 | ||
5 | static int minx,maxx,miny,maxy,k,m; | |
6 | static char bot1f=0,bot2f=0,bot3f=0; | |
7 | char always=0; | |
8 | /* | |
9 | bottomline() | |
10 | ||
11 | now for the bottom line of the display | |
12 | */ | |
13 | bottomline() | |
14 | { recalc(); bot1f=1; } | |
15 | bottomhp() | |
16 | { bot2f=1; } | |
17 | bottomspell() | |
18 | { bot3f=1; } | |
19 | bottomdo() | |
20 | { | |
21 | if (bot1f) { bot3f=bot1f=bot2f=0; bot_linex(); return; } | |
22 | if (bot2f) { bot2f=0; bot_hpx(); } | |
23 | if (bot3f) { bot3f=0; bot_spellx(); } | |
24 | } | |
25 | ||
26 | static void botsub(); | |
27 | ||
28 | bot_linex() | |
29 | { | |
30 | register int i; | |
31 | if (cbak[SPELLS] <= -50 || (always)) | |
32 | { | |
33 | cursor( 1,18); | |
34 | if (c[SPELLMAX]>99) lprintf("Spells:%3d(%3d)",(long)c[SPELLS],(long)c[SPELLMAX]); | |
35 | else lprintf("Spells:%3d(%2d) ",(long)c[SPELLS],(long)c[SPELLMAX]); | |
36 | lprintf(" AC: %-3d WC: %-3d Level",(long)c[AC],(long)c[WCLASS]); | |
37 | if (c[LEVEL]>99) lprintf("%3d",(long)c[LEVEL]); | |
38 | else lprintf(" %-2d",(long)c[LEVEL]); | |
39 | lprintf(" Exp: %-9d %s\n",(long)c[EXPERIENCE],class[c[LEVEL]-1]); | |
40 | lprintf("HP: %3d(%3d) STR=%-2d INT=%-2d ", | |
41 | (long)c[HP],(long)c[HPMAX],(long)(c[STRENGTH]+c[STREXTRA]),(long)c[INTELLIGENCE]); | |
42 | lprintf("WIS=%-2d CON=%-2d DEX=%-2d CHA=%-2d LV:", | |
43 | (long)c[WISDOM],(long)c[CONSTITUTION],(long)c[DEXTERITY],(long)c[CHARISMA]); | |
44 | ||
45 | if ((level==0) || (wizard)) c[TELEFLAG]=0; | |
46 | if (c[TELEFLAG]) lprcat(" ?"); else lprcat(levelname[level]); | |
47 | lprintf(" Gold: %-6d",(long)c[GOLD]); | |
48 | always=1; botside(); | |
49 | c[TMP] = c[STRENGTH]+c[STREXTRA]; | |
50 | for (i=0; i<100; i++) cbak[i]=c[i]; | |
51 | return; | |
52 | } | |
53 | ||
54 | botsub(makecode(SPELLS,8,18),"%3d"); | |
55 | if (c[SPELLMAX]>99) botsub(makecode(SPELLMAX,12,18),"%3d)"); | |
56 | else botsub(makecode(SPELLMAX,12,18),"%2d) "); | |
57 | botsub(makecode(HP,5,19),"%3d"); | |
58 | botsub(makecode(HPMAX,9,19),"%3d"); | |
59 | botsub(makecode(AC,21,18),"%-3d"); | |
60 | botsub(makecode(WCLASS,30,18),"%-3d"); | |
61 | botsub(makecode(EXPERIENCE,49,18),"%-9d"); | |
62 | if (c[LEVEL] != cbak[LEVEL]) | |
63 | { cursor(59,18); lprcat(class[c[LEVEL]-1]); } | |
64 | if (c[LEVEL]>99) botsub(makecode(LEVEL,40,18),"%3d"); | |
65 | else botsub(makecode(LEVEL,40,18)," %-2d"); | |
66 | c[TMP] = c[STRENGTH]+c[STREXTRA]; botsub(makecode(TMP,18,19),"%-2d"); | |
67 | botsub(makecode(INTELLIGENCE,25,19),"%-2d"); | |
68 | botsub(makecode(WISDOM,32,19),"%-2d"); | |
69 | botsub(makecode(CONSTITUTION,39,19),"%-2d"); | |
70 | botsub(makecode(DEXTERITY,46,19),"%-2d"); | |
71 | botsub(makecode(CHARISMA,53,19),"%-2d"); | |
72 | if ((level != cbak[CAVELEVEL]) || (c[TELEFLAG] != cbak[TELEFLAG])) | |
73 | { | |
74 | if ((level==0) || (wizard)) c[TELEFLAG]=0; | |
75 | cbak[TELEFLAG] = c[TELEFLAG]; | |
76 | cbak[CAVELEVEL] = level; cursor(59,19); | |
77 | if (c[TELEFLAG]) lprcat(" ?"); else lprcat(levelname[level]); | |
78 | } | |
79 | botsub(makecode(GOLD,69,19),"%-6d"); | |
80 | botside(); | |
81 | } | |
82 | ||
83 | /* | |
84 | special subroutine to update only the gold number on the bottomlines | |
85 | called from ogold() | |
86 | */ | |
87 | bottomgold() | |
88 | { | |
89 | botsub(makecode(GOLD,69,19),"%-6d"); | |
90 | /* botsub(GOLD,"%-6d",69,19); */ | |
91 | } | |
92 | ||
93 | /* | |
94 | special routine to update hp and level fields on bottom lines | |
95 | called in monster.c hitplayer() and spattack() | |
96 | */ | |
97 | bot_hpx() | |
98 | { | |
99 | if (c[EXPERIENCE] != cbak[EXPERIENCE]) | |
100 | { | |
101 | recalc(); bot_linex(); | |
102 | } | |
103 | else botsub(makecode(HP,5,19),"%3d"); | |
104 | } | |
105 | ||
106 | /* | |
107 | special routine to update number of spells called from regen() | |
108 | */ | |
109 | bot_spellx() | |
110 | { | |
111 | botsub(makecode(SPELLS,9,18),"%2d"); | |
112 | } | |
113 | ||
114 | /* | |
115 | common subroutine for a more economical bottomline() | |
116 | */ | |
117 | static struct bot_side_def | |
118 | { | |
119 | int typ; | |
120 | char *string; | |
121 | } | |
122 | bot_data[] = | |
123 | { | |
124 | STEALTH,"stealth", UNDEADPRO,"undead pro", SPIRITPRO,"spirit pro", | |
125 | CHARMCOUNT,"Charm", TIMESTOP,"Time Stop", HOLDMONST,"Hold Monst", | |
126 | GIANTSTR,"Giant Str", FIRERESISTANCE,"Fire Resit", DEXCOUNT,"Dexterity", | |
127 | STRCOUNT,"Strength", SCAREMONST,"Scare", HASTESELF,"Haste Self", | |
128 | CANCELLATION,"Cancel", INVISIBILITY,"Invisible", ALTPRO,"Protect 3", | |
129 | PROTECTIONTIME,"Protect 2", WTW,"Wall-Walk" | |
130 | }; | |
131 | ||
132 | botside() | |
133 | { | |
134 | register int i,idx; | |
135 | for (i=0; i<17; i++) | |
136 | { | |
137 | idx = bot_data[i].typ; | |
138 | if ((always) || (c[idx] != cbak[idx])) | |
139 | { | |
140 | if ((always) || (cbak[idx] == 0)) | |
141 | { if (c[idx]) { cursor(70,i+1); lprcat(bot_data[i].string); } } else | |
142 | if (c[idx]==0) { cursor(70,i+1); lprcat(" "); } | |
143 | cbak[idx]=c[idx]; | |
144 | } | |
145 | } | |
146 | always=0; | |
147 | } | |
148 | ||
149 | static void | |
150 | botsub(idx,str) | |
151 | register int idx; | |
152 | char *str; | |
153 | { | |
154 | register int x,y; | |
155 | y = idx & 0xff; x = (idx>>8) & 0xff; idx >>= 16; | |
156 | if (c[idx] != cbak[idx]) | |
157 | { cbak[idx]=c[idx]; cursor(x,y); lprintf(str,(long)c[idx]); } | |
158 | } | |
159 | ||
160 | /* | |
161 | * subroutine to draw only a section of the screen | |
162 | * only the top section of the screen is updated. If entire lines are being | |
163 | * drawn, then they will be cleared first. | |
164 | */ | |
165 | int d_xmin=0,d_xmax=MAXX,d_ymin=0,d_ymax=MAXY; /* for limited screen drawing */ | |
166 | draws(xmin,xmax,ymin,ymax) | |
167 | int xmin,xmax,ymin,ymax; | |
168 | { | |
169 | register int i,idx; | |
170 | if (xmin==0 && xmax==MAXX) /* clear section of screen as needed */ | |
171 | { | |
172 | if (ymin==0) cl_up(79,ymax); | |
173 | else for (i=ymin; i<ymin; i++) cl_line(1,i+1); | |
174 | xmin = -1; | |
175 | } | |
176 | d_xmin=xmin; d_xmax=xmax; d_ymin=ymin; d_ymax=ymax; /* for limited screen drawing */ | |
177 | drawscreen(); | |
178 | if (xmin<=0 && xmax==MAXX) /* draw stuff on right side of screen as needed*/ | |
179 | { | |
180 | for (i=ymin; i<ymax; i++) | |
181 | { | |
182 | idx = bot_data[i].typ; | |
183 | if (c[idx]) | |
184 | { | |
185 | cursor(70,i+1); lprcat(bot_data[i].string); | |
186 | } | |
187 | cbak[idx]=c[idx]; | |
188 | } | |
189 | } | |
190 | } | |
191 | ||
192 | /* | |
193 | drawscreen() | |
194 | ||
195 | subroutine to redraw the whole screen as the player knows it | |
196 | */ | |
197 | char screen[MAXX][MAXY],d_flag; /* template for the screen */ | |
198 | drawscreen() | |
199 | { | |
200 | register int i,j,k; | |
201 | int lastx,lasty; /* variables used to optimize the object printing */ | |
202 | if (d_xmin==0 && d_xmax==MAXX && d_ymin==0 && d_ymax==MAXY) | |
203 | { | |
204 | d_flag=1; clear(); /* clear the screen */ | |
205 | } | |
206 | else | |
207 | { | |
208 | d_flag=0; cursor(1,1); | |
209 | } | |
210 | if (d_xmin<0) | |
211 | d_xmin=0; /* d_xmin=-1 means display all without bottomline */ | |
212 | ||
213 | for (i=d_ymin; i<d_ymax; i++) | |
214 | for (j=d_xmin; j<d_xmax; j++) | |
215 | if (know[j][i]==0) screen[j][i] = ' '; else | |
216 | if (k=mitem[j][i]) screen[j][i] = monstnamelist[k]; else | |
217 | if ((k=item[j][i])==OWALL) screen[j][i] = '#'; | |
218 | else screen[j][i] = ' '; | |
219 | ||
220 | for (i=d_ymin; i<d_ymax; i++) | |
221 | { | |
222 | j=d_xmin; while ((screen[j][i]==' ') && (j<d_xmax)) j++; | |
223 | /* was m=0 */ | |
224 | if (j >= d_xmax) m=d_xmin; /* don't search backwards if blank line */ | |
225 | else | |
226 | { /* search backwards for end of line */ | |
227 | m=d_xmax-1; while ((screen[m][i]==' ') && (m>d_xmin)) --m; | |
228 | if (j<=m) cursor(j+1,i+1); else continue; | |
229 | } | |
230 | while (j <= m) | |
231 | { | |
232 | if (j <= m-3) | |
233 | { | |
234 | for (k=j; k<=j+3; k++) if (screen[k][i] != ' ') k=1000; | |
235 | if (k < 1000) | |
236 | { while(screen[j][i]==' ' && j<=m) j++; cursor(j+1,i+1); } | |
237 | } | |
238 | lprc(screen[j++][i]); | |
239 | } | |
240 | } | |
241 | setbold(); /* print out only bold objects now */ | |
242 | ||
243 | for (lastx=lasty=127, i=d_ymin; i<d_ymax; i++) | |
244 | for (j=d_xmin; j<d_xmax; j++) | |
245 | { | |
246 | if (k=item[j][i]) | |
247 | if (k != OWALL) | |
248 | if ((know[j][i]) && (mitem[j][i]==0)) | |
249 | if (objnamelist[k]!=' ') | |
250 | { | |
251 | if (lasty!=i+1 || lastx!=j) | |
252 | cursor(lastx=j+1,lasty=i+1); else lastx++; | |
253 | lprc(objnamelist[k]); | |
254 | } | |
255 | } | |
256 | ||
257 | resetbold(); if (d_flag) { always=1; botside(); always=1; bot_linex(); } | |
258 | oldx=99; | |
259 | d_xmin = 0 , d_xmax = MAXX , d_ymin = 0 , d_ymax = MAXY; /* for limited screen drawing */ | |
260 | } | |
261 | \f | |
262 | /* | |
263 | showcell(x,y) | |
264 | ||
265 | subroutine to display a cell location on the screen | |
266 | */ | |
267 | showcell(x,y) | |
268 | int x,y; | |
269 | { | |
270 | register int i,j,k,m; | |
271 | if (c[BLINDCOUNT]) return; /* see nothing if blind */ | |
272 | if (c[AWARENESS]) { minx = x-3; maxx = x+3; miny = y-3; maxy = y+3; } | |
273 | else { minx = x-1; maxx = x+1; miny = y-1; maxy = y+1; } | |
274 | ||
275 | if (minx < 0) minx=0; if (maxx > MAXX-1) maxx = MAXX-1; | |
276 | if (miny < 0) miny=0; if (maxy > MAXY-1) maxy = MAXY-1; | |
277 | ||
278 | for (j=miny; j<=maxy; j++) | |
279 | for (m=minx; m<=maxx; m++) | |
280 | if (know[m][j]==0) | |
281 | { | |
282 | cursor(m+1,j+1); | |
283 | x=maxx; while (know[x][j]) --x; | |
284 | for (i=m; i<=x; i++) | |
285 | { | |
286 | if ((k=mitem[i][j]) != 0) lprc(monstnamelist[k]); | |
287 | else switch(k=item[i][j]) | |
288 | { | |
289 | case OWALL: case 0: case OIVTELETRAP: case OTRAPARROWIV: | |
290 | case OIVDARTRAP: case OIVTRAPDOOR: | |
291 | lprc(objnamelist[k]); break; | |
292 | ||
293 | default: setbold(); lprc(objnamelist[k]); resetbold(); | |
294 | }; | |
295 | know[i][j]=1; | |
296 | } | |
297 | m = maxx; | |
298 | } | |
299 | } | |
300 | ||
301 | /* | |
302 | this routine shows only the spot that is given it. the spaces around | |
303 | these coordinated are not shown | |
304 | used in godirect() in monster.c for missile weapons display | |
305 | */ | |
306 | show1cell(x,y) | |
307 | int x,y; | |
308 | { | |
309 | if (c[BLINDCOUNT]) return; /* see nothing if blind */ | |
310 | cursor(x+1,y+1); | |
311 | if ((k=mitem[x][y]) != 0) lprc(monstnamelist[k]); | |
312 | else switch(k=item[x][y]) | |
313 | { | |
314 | case OWALL: case 0: case OIVTELETRAP: case OTRAPARROWIV: | |
315 | case OIVDARTRAP: case OIVTRAPDOOR: | |
316 | lprc(objnamelist[k]); break; | |
317 | ||
318 | default: setbold(); lprc(objnamelist[k]); resetbold(); | |
319 | }; | |
320 | know[x][y]|=1; /* we end up knowing about it */ | |
321 | } | |
322 | ||
323 | /* | |
324 | showplayer() | |
325 | ||
326 | subroutine to show where the player is on the screen | |
327 | cursor values start from 1 up | |
328 | */ | |
329 | showplayer() | |
330 | { | |
331 | cursor(playerx+1,playery+1); | |
332 | oldx=playerx; oldy=playery; | |
333 | } | |
334 | ||
335 | /* | |
336 | moveplayer(dir) | |
337 | ||
338 | subroutine to move the player from one room to another | |
339 | returns 0 if can't move in that direction or hit a monster or on an object | |
340 | else returns 1 | |
341 | nomove is set to 1 to stop the next move (inadvertent monsters hitting | |
342 | players when walking into walls) if player walks off screen or into wall | |
343 | */ | |
344 | short diroffx[] = { 0, 0, 1, 0, -1, 1, -1, 1, -1 }; | |
345 | short diroffy[] = { 0, 1, 0, -1, 0, -1, -1, 1, 1 }; | |
346 | moveplayer(dir) | |
347 | int dir; /* from = present room # direction = [1-north] | |
348 | [2-east] [3-south] [4-west] [5-northeast] | |
349 | [6-northwest] [7-southeast] [8-southwest] | |
350 | if direction=0, don't move--just show where he is */ | |
351 | { | |
352 | register int k,m,i,j; | |
353 | if (c[CONFUSE]) if (c[LEVEL]<rnd(30)) dir=rund(9); /*if confused any dir*/ | |
354 | k = playerx + diroffx[dir]; m = playery + diroffy[dir]; | |
355 | if (k<0 || k>=MAXX || m<0 || m>=MAXY) { nomove=1; return(yrepcount = 0); } | |
356 | i = item[k][m]; j = mitem[k][m]; | |
357 | if (i==OWALL && c[WTW]==0) { nomove=1; return(yrepcount = 0); } /* hit a wall */ | |
358 | if (k==33 && m==MAXY-1 && level==1) | |
359 | { | |
360 | newcavelevel(0); for (k=0; k<MAXX; k++) for (m=0; m<MAXY; m++) | |
361 | if (item[k][m]==OENTRANCE) | |
362 | { playerx=k; playery=m; positionplayer(); drawscreen(); return(0); } | |
363 | } | |
364 | if (j>0) { hitmonster(k,m); return(yrepcount = 0); } /* hit a monster*/ | |
365 | lastpx = playerx; lastpy = playery; | |
366 | playerx = k; playery = m; | |
367 | if (i && i!=OTRAPARROWIV && i!=OIVTELETRAP && i!=OIVDARTRAP && i!=OIVTRAPDOOR) return(yrepcount = 0); else return(1); | |
368 | } | |
369 | \f | |
370 | /* | |
371 | * function to show what magic items have been discovered thus far | |
372 | * enter with -1 for just spells, anything else will give scrolls & potions | |
373 | */ | |
374 | static int lincount,count; | |
375 | seemagic(arg) | |
376 | int arg; | |
377 | { | |
378 | register int i,number; | |
379 | count = lincount = 0; nosignal=1; | |
380 | ||
381 | if (arg== -1) /* if display spells while casting one */ | |
382 | { | |
383 | for (number=i=0; i<SPNUM; i++) if (spelknow[i]) number++; | |
384 | number = (number+2)/3 + 4; /* # lines needed to display */ | |
385 | cl_up(79,number); cursor(1,1); | |
386 | } | |
387 | else | |
388 | { | |
389 | resetscroll(); clear(); | |
390 | } | |
391 | ||
392 | lprcat("The magic spells you have discovered thus far:\n\n"); | |
393 | for (i=0; i<SPNUM; i++) | |
394 | if (spelknow[i]) | |
395 | { lprintf("%s %-20s ",spelcode[i],spelname[i]); seepage(); } | |
396 | ||
397 | if (arg== -1) | |
398 | { | |
399 | seepage(); more(); nosignal=0; | |
400 | draws(0,MAXX,0,number); return; | |
401 | } | |
402 | ||
403 | lincount += 3; if (count!=0) { count=2; seepage(); } | |
404 | ||
405 | lprcat("\nThe magic scrolls you have found to date are:\n\n"); | |
406 | count=0; | |
407 | for (i=0; i<MAXSCROLL; i++) | |
408 | if (scrollname[i][0]) | |
409 | if (scrollname[i][1]!=' ') | |
410 | { lprintf("%-26s",&scrollname[i][1]); seepage(); } | |
411 | ||
412 | lincount += 3; if (count!=0) { count=2; seepage(); } | |
413 | ||
414 | lprcat("\nThe magic potions you have found to date are:\n\n"); | |
415 | count=0; | |
416 | for (i=0; i<MAXPOTION; i++) | |
417 | if (potionname[i][0]) | |
418 | if (potionname[i][1]!=' ') | |
419 | { lprintf("%-26s",&potionname[i][1]); seepage(); } | |
420 | ||
421 | if (lincount!=0) more(); nosignal=0; setscroll(); drawscreen(); | |
422 | } | |
423 | ||
424 | /* | |
425 | * subroutine to paginate the seemagic function | |
426 | */ | |
427 | seepage() | |
428 | { | |
429 | if (++count==3) | |
430 | { | |
431 | lincount++; count=0; lprc('\n'); | |
432 | if (lincount>17) { lincount=0; more(); clear(); } | |
433 | } | |
434 | } |