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