display.c revision 1.1 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
262 /*
264 showcell(x,y)
265
266 subroutine to display a cell location on the screen
267 */
268 showcell(x,y)
269 int x,y;
270 {
271 register int i,j,k,m;
272 if (c[BLINDCOUNT]) return; /* see nothing if blind */
273 if (c[AWARENESS]) { minx = x-3; maxx = x+3; miny = y-3; maxy = y+3; }
274 else { minx = x-1; maxx = x+1; miny = y-1; maxy = y+1; }
275
276 if (minx < 0) minx=0; if (maxx > MAXX-1) maxx = MAXX-1;
277 if (miny < 0) miny=0; if (maxy > MAXY-1) maxy = MAXY-1;
278
279 for (j=miny; j<=maxy; j++)
280 for (m=minx; m<=maxx; m++)
281 if (know[m][j]==0)
282 {
283 cursor(m+1,j+1);
284 x=maxx; while (know[x][j]) --x;
285 for (i=m; i<=x; i++)
286 {
287 if ((k=mitem[i][j]) != 0) lprc(monstnamelist[k]);
288 else switch(k=item[i][j])
289 {
290 case OWALL: case 0: case OIVTELETRAP: case OTRAPARROWIV:
291 case OIVDARTRAP: case OIVTRAPDOOR:
292 lprc(objnamelist[k]); break;
293
294 default: setbold(); lprc(objnamelist[k]); resetbold();
295 };
296 know[i][j]=1;
297 }
298 m = maxx;
299 }
300 }
301
302 /*
303 this routine shows only the spot that is given it. the spaces around
304 these coordinated are not shown
305 used in godirect() in monster.c for missile weapons display
306 */
307 show1cell(x,y)
308 int x,y;
309 {
310 if (c[BLINDCOUNT]) return; /* see nothing if blind */
311 cursor(x+1,y+1);
312 if ((k=mitem[x][y]) != 0) lprc(monstnamelist[k]);
313 else switch(k=item[x][y])
314 {
315 case OWALL: case 0: case OIVTELETRAP: case OTRAPARROWIV:
316 case OIVDARTRAP: case OIVTRAPDOOR:
317 lprc(objnamelist[k]); break;
318
319 default: setbold(); lprc(objnamelist[k]); resetbold();
320 };
321 know[x][y]|=1; /* we end up knowing about it */
322 }
323
324 /*
325 showplayer()
326
327 subroutine to show where the player is on the screen
328 cursor values start from 1 up
329 */
330 showplayer()
331 {
332 cursor(playerx+1,playery+1);
333 oldx=playerx; oldy=playery;
334 }
335
336 /*
337 moveplayer(dir)
338
339 subroutine to move the player from one room to another
340 returns 0 if can't move in that direction or hit a monster or on an object
341 else returns 1
342 nomove is set to 1 to stop the next move (inadvertent monsters hitting
343 players when walking into walls) if player walks off screen or into wall
344 */
345 short diroffx[] = { 0, 0, 1, 0, -1, 1, -1, 1, -1 };
346 short diroffy[] = { 0, 1, 0, -1, 0, -1, -1, 1, 1 };
347 moveplayer(dir)
348 int dir; /* from = present room # direction = [1-north]
349 [2-east] [3-south] [4-west] [5-northeast]
350 [6-northwest] [7-southeast] [8-southwest]
351 if direction=0, don't move--just show where he is */
352 {
353 register int k,m,i,j;
354 if (c[CONFUSE]) if (c[LEVEL]<rnd(30)) dir=rund(9); /*if confused any dir*/
355 k = playerx + diroffx[dir]; m = playery + diroffy[dir];
356 if (k<0 || k>=MAXX || m<0 || m>=MAXY) { nomove=1; return(yrepcount = 0); }
357 i = item[k][m]; j = mitem[k][m];
358 if (i==OWALL && c[WTW]==0) { nomove=1; return(yrepcount = 0); } /* hit a wall */
359 if (k==33 && m==MAXY-1 && level==1)
360 {
361 newcavelevel(0); for (k=0; k<MAXX; k++) for (m=0; m<MAXY; m++)
362 if (item[k][m]==OENTRANCE)
363 { playerx=k; playery=m; positionplayer(); drawscreen(); return(0); }
364 }
365 if (j>0) { hitmonster(k,m); return(yrepcount = 0); } /* hit a monster*/
366 lastpx = playerx; lastpy = playery;
367 playerx = k; playery = m;
368 if (i && i!=OTRAPARROWIV && i!=OIVTELETRAP && i!=OIVDARTRAP && i!=OIVTRAPDOOR) return(yrepcount = 0); else return(1);
369 }
370
371 /*
373 * function to show what magic items have been discovered thus far
374 * enter with -1 for just spells, anything else will give scrolls & potions
375 */
376 static int lincount,count;
377 seemagic(arg)
378 int arg;
379 {
380 register int i,number;
381 count = lincount = 0; nosignal=1;
382
383 if (arg== -1) /* if display spells while casting one */
384 {
385 for (number=i=0; i<SPNUM; i++) if (spelknow[i]) number++;
386 number = (number+2)/3 + 4; /* # lines needed to display */
387 cl_up(79,number); cursor(1,1);
388 }
389 else
390 {
391 resetscroll(); clear();
392 }
393
394 lprcat("The magic spells you have discovered thus far:\n\n");
395 for (i=0; i<SPNUM; i++)
396 if (spelknow[i])
397 { lprintf("%s %-20s ",spelcode[i],spelname[i]); seepage(); }
398
399 if (arg== -1)
400 {
401 seepage(); more(); nosignal=0;
402 draws(0,MAXX,0,number); return;
403 }
404
405 lincount += 3; if (count!=0) { count=2; seepage(); }
406
407 lprcat("\nThe magic scrolls you have found to date are:\n\n");
408 count=0;
409 for (i=0; i<MAXSCROLL; i++)
410 if (scrollname[i][0])
411 if (scrollname[i][1]!=' ')
412 { lprintf("%-26s",&scrollname[i][1]); seepage(); }
413
414 lincount += 3; if (count!=0) { count=2; seepage(); }
415
416 lprcat("\nThe magic potions you have found to date are:\n\n");
417 count=0;
418 for (i=0; i<MAXPOTION; i++)
419 if (potionname[i][0])
420 if (potionname[i][1]!=' ')
421 { lprintf("%-26s",&potionname[i][1]); seepage(); }
422
423 if (lincount!=0) more(); nosignal=0; setscroll(); drawscreen();
424 }
425
426 /*
427 * subroutine to paginate the seemagic function
428 */
429 seepage()
430 {
431 if (++count==3)
432 {
433 lincount++; count=0; lprc('\n');
434 if (lincount>17) { lincount=0; more(); clear(); }
435 }
436 }
437