date and time created 89/03/05 18:59:16 by bostic
[unix-history] / usr / src / games / larn / display.c
CommitLineData
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
5static int minx,maxx,miny,maxy,k,m;
6static char bot1f=0,bot2f=0,bot3f=0;
7char always=0;
8/*
9 bottomline()
10
11 now for the bottom line of the display
12 */
13bottomline()
14 { recalc(); bot1f=1; }
15bottomhp()
16 { bot2f=1; }
17bottomspell()
18 { bot3f=1; }
19bottomdo()
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
26bot_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 */
85bottomgold()
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 */
95bot_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 */
107bot_spellx()
108 {
109 botsub(makecode(SPELLS,9,18),"%2d");
110 }
111
112/*
113 common subroutine for a more economical bottomline()
114 */
115static 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
130botside()
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
147static 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 */
162int d_xmin=0,d_xmax=MAXX,d_ymin=0,d_ymax=MAXY; /* for limited screen drawing */
163draws(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 */
194char screen[MAXX][MAXY],d_flag; /* template for the screen */
195drawscreen()
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 */
264showcell(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 */
303show1cell(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 */
326showplayer()
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 */
341short diroffx[] = { 0, 0, 1, 0, -1, 1, -1, 1, -1 };
342short diroffy[] = { 0, 1, 0, -1, 0, -1, -1, 1, 1 };
343moveplayer(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 */
371static int lincount,count;
372seemagic(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 */
424seepage()
425 {
426 if (++count==3)
427 {
428 lincount++; count=0; lprc('\n');
429 if (lincount>17) { lincount=0; more(); clear(); }
430 }
431 }