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