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