Install dma(8) config files with mode 640 as root:mail to prevent ``normal''
[dragonfly/netmp.git] / games / larn / display.c
blob23f0a078171e73aa6125d6b2a2d9af73b4c76f9f
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.3 2006/08/26 17:05:05 pavalos Exp $ */
4 #include "header.h"
5 #define makecode(_a,_b,_c) (((_a)<<16) + ((_b)<<8) + (_c))
7 static int minx,maxx,miny,maxy,k,m;
8 static char bot1f=0,bot2f=0,bot3f=0;
9 char always=0;
11 static void bot_hpx(void);
12 static void bot_spellx(void);
13 static void botside(void);
14 static void botsub(int, const char *);
15 static void seepage(void);
18 bottomline()
20 now for the bottom line of the display
22 void
23 bottomline(void)
24 { recalc(); bot1f=1; }
25 void
26 bottomhp(void)
27 { bot2f=1; }
28 void
29 bottomspell(void)
30 { bot3f=1; }
31 void
32 bottomdo(void)
34 if (bot1f) { bot3f=bot1f=bot2f=0; bot_linex(); return; }
35 if (bot2f) { bot2f=0; bot_hpx(); }
36 if (bot3f) { bot3f=0; bot_spellx(); }
39 void
40 bot_linex(void)
42 int i;
43 if (cbak[SPELLS] <= -50 || (always))
45 cursor( 1,18);
46 if (c[SPELLMAX]>99) lprintf("Spells:%3d(%3d)",(long)c[SPELLS],(long)c[SPELLMAX]);
47 else lprintf("Spells:%3d(%2d) ",(long)c[SPELLS],(long)c[SPELLMAX]);
48 lprintf(" AC: %-3d WC: %-3d Level",(long)c[AC],(long)c[WCLASS]);
49 if (c[LEVEL]>99) lprintf("%3d",(long)c[LEVEL]);
50 else lprintf(" %-2d",(long)c[LEVEL]);
51 lprintf(" Exp: %-9d %s\n",(long)c[EXPERIENCE],class[c[LEVEL]-1]);
52 lprintf("HP: %3d(%3d) STR=%-2d INT=%-2d ",
53 (long)c[HP],(long)c[HPMAX],(long)(c[STRENGTH]+c[STREXTRA]),(long)c[INTELLIGENCE]);
54 lprintf("WIS=%-2d CON=%-2d DEX=%-2d CHA=%-2d LV:",
55 (long)c[WISDOM],(long)c[CONSTITUTION],(long)c[DEXTERITY],(long)c[CHARISMA]);
57 if ((level==0) || (wizard)) c[TELEFLAG]=0;
58 if (c[TELEFLAG]) lprcat(" ?"); else lprcat(levelname[(int)level]);
59 lprintf(" Gold: %-6d",(long)c[GOLD]);
60 always=1; botside();
61 c[TMP] = c[STRENGTH]+c[STREXTRA];
62 for (i=0; i<100; i++) cbak[i]=c[i];
63 return;
66 botsub(makecode(SPELLS,8,18),"%3d");
67 if (c[SPELLMAX]>99) botsub(makecode(SPELLMAX,12,18),"%3d)");
68 else botsub(makecode(SPELLMAX,12,18),"%2d) ");
69 botsub(makecode(HP,5,19),"%3d");
70 botsub(makecode(HPMAX,9,19),"%3d");
71 botsub(makecode(AC,21,18),"%-3d");
72 botsub(makecode(WCLASS,30,18),"%-3d");
73 botsub(makecode(EXPERIENCE,49,18),"%-9d");
74 if (c[LEVEL] != cbak[LEVEL])
75 { cursor(59,18); lprcat(class[c[LEVEL]-1]); }
76 if (c[LEVEL]>99) botsub(makecode(LEVEL,40,18),"%3d");
77 else botsub(makecode(LEVEL,40,18)," %-2d");
78 c[TMP] = c[STRENGTH]+c[STREXTRA]; botsub(makecode(TMP,18,19),"%-2d");
79 botsub(makecode(INTELLIGENCE,25,19),"%-2d");
80 botsub(makecode(WISDOM,32,19),"%-2d");
81 botsub(makecode(CONSTITUTION,39,19),"%-2d");
82 botsub(makecode(DEXTERITY,46,19),"%-2d");
83 botsub(makecode(CHARISMA,53,19),"%-2d");
84 if ((level != cbak[CAVELEVEL]) || (c[TELEFLAG] != cbak[TELEFLAG]))
86 if ((level==0) || (wizard)) c[TELEFLAG]=0;
87 cbak[TELEFLAG] = c[TELEFLAG];
88 cbak[CAVELEVEL] = level; cursor(59,19);
89 if (c[TELEFLAG]) lprcat(" ?"); else lprcat(levelname[(int)level]);
91 botsub(makecode(GOLD,69,19),"%-6d");
92 botside();
96 special subroutine to update only the gold number on the bottomlines
97 called from ogold()
99 void
100 bottomgold(void)
102 botsub(makecode(GOLD,69,19),"%-6d");
106 special routine to update hp and level fields on bottom lines
107 called in monster.c hitplayer() and spattack()
109 static void
110 bot_hpx(void)
112 if (c[EXPERIENCE] != cbak[EXPERIENCE])
114 recalc(); bot_linex();
116 else botsub(makecode(HP,5,19),"%3d");
120 special routine to update number of spells called from regen()
122 static void
123 bot_spellx(void)
125 botsub(makecode(SPELLS,9,18),"%2d");
129 common subroutine for a more economical bottomline()
131 static struct bot_side_def
133 int typ;
134 const char *string;
136 bot_data[] =
138 { STEALTH, "stealth" }, { UNDEADPRO, "undead pro" }, { SPIRITPRO, "spirit pro" },
139 { CHARMCOUNT, "Charm" }, { TIMESTOP, "Time Stop" }, { HOLDMONST, "Hold Monst" },
140 { GIANTSTR, "Giant Str" }, { FIRERESISTANCE, "Fire Resit" }, { DEXCOUNT, "Dexterity" },
141 { STRCOUNT, "Strength" }, { SCAREMONST, "Scare" }, { HASTESELF, "Haste Self" },
142 { CANCELLATION, "Cancel" }, { INVISIBILITY, "Invisible" }, { ALTPRO, "Protect 3" },
143 { PROTECTIONTIME, "Protect 2" }, { WTW, "Wall-Walk"}
146 static void
147 botside(void)
149 int i,idx;
150 for (i=0; i<17; i++)
152 idx = bot_data[i].typ;
153 if ((always) || (c[idx] != cbak[idx]))
155 if ((always) || (cbak[idx] == 0))
156 { if (c[idx]) { cursor(70,i+1); lprcat(bot_data[i].string); } } else
157 if (c[idx]==0) { cursor(70,i+1); lprcat(" "); }
158 cbak[idx]=c[idx];
161 always=0;
164 static void
165 botsub(int idx, const char *str)
167 int x,y;
168 y = idx & 0xff; x = (idx>>8) & 0xff; idx >>= 16;
169 if (c[idx] != cbak[idx])
170 { cbak[idx]=c[idx]; cursor(x,y); lprintf(str,(long)c[idx]); }
174 * subroutine to draw only a section of the screen
175 * only the top section of the screen is updated. If entire lines are being
176 * drawn, then they will be cleared first.
178 int d_xmin=0,d_xmax=MAXX,d_ymin=0,d_ymax=MAXY; /* for limited screen drawing */
180 void
181 draws(int xmin, int xmax, int ymin, int ymax)
183 int i,idx;
184 if (xmin==0 && xmax==MAXX) /* clear section of screen as needed */
186 if (ymin==0) cl_up(79,ymax);
187 else for (i=ymin; i<ymin; i++) cl_line(1,i+1);
188 xmin = -1;
190 d_xmin=xmin; d_xmax=xmax; d_ymin=ymin; d_ymax=ymax; /* for limited screen drawing */
191 drawscreen();
192 if (xmin<=0 && xmax==MAXX) /* draw stuff on right side of screen as needed*/
194 for (i=ymin; i<ymax; i++)
196 idx = bot_data[i].typ;
197 if (c[idx])
199 cursor(70,i+1); lprcat(bot_data[i].string);
201 cbak[idx]=c[idx];
207 drawscreen()
209 subroutine to redraw the whole screen as the player knows it
211 char screen[MAXX][MAXY],d_flag; /* template for the screen */
213 void
214 drawscreen(void)
216 int i,j,l;
217 int lastx,lasty; /* variables used to optimize the object printing */
218 if (d_xmin==0 && d_xmax==MAXX && d_ymin==0 && d_ymax==MAXY)
220 d_flag=1; clear(); /* clear the screen */
222 else
224 d_flag=0; cursor(1,1);
226 if (d_xmin<0)
227 d_xmin=0; /* d_xmin=-1 means display all without bottomline */
229 for (i=d_ymin; i<d_ymax; i++)
230 for (j=d_xmin; j<d_xmax; j++)
231 if (know[j][i]==0) screen[j][i] = ' '; else
232 if ((l=mitem[j][i])) screen[j][i] = monstnamelist[l]; else
233 if ((l=item[j][i])==OWALL) screen[j][i] = '#';
234 else screen[j][i] = ' ';
236 for (i=d_ymin; i<d_ymax; i++)
238 j=d_xmin; while ((screen[j][i]==' ') && (j<d_xmax)) j++;
239 /* was m=0 */
240 if (j >= d_xmax) m=d_xmin; /* don't search backwards if blank line */
241 else
242 { /* search backwards for end of line */
243 m=d_xmax-1; while ((screen[m][i]==' ') && (m>d_xmin)) --m;
244 if (j<=m) cursor(j+1,i+1); else continue;
246 while (j <= m)
248 if (j <= m-3)
250 for (l=j; l<=j+3; l++) if (screen[l][i] != ' ') l=1000;
251 if (l < 1000)
252 { while(screen[j][i]==' ' && j<=m) j++; cursor(j+1,i+1); }
254 lprc(screen[j++][i]);
257 setbold(); /* print out only bold objects now */
259 for (lastx=lasty=127, i=d_ymin; i<d_ymax; i++)
260 for (j=d_xmin; j<d_xmax; j++)
262 if ((l=item[j][i]))
263 if (l != OWALL)
264 if ((know[j][i]) && (mitem[j][i]==0))
265 if (objnamelist[l]!=' ')
267 if (lasty!=i+1 || lastx!=j)
268 cursor(lastx=j+1,lasty=i+1); else lastx++;
269 lprc(objnamelist[l]);
273 resetbold(); if (d_flag) { always=1; botside(); always=1; bot_linex(); }
274 oldx=99;
275 d_xmin = 0 , d_xmax = MAXX , d_ymin = 0 , d_ymax = MAXY; /* for limited screen drawing */
279 showcell(x,y)
281 subroutine to display a cell location on the screen
283 void
284 showcell(int x, int y)
286 int i,j,l,n;
287 if (c[BLINDCOUNT]) return; /* see nothing if blind */
288 if (c[AWARENESS]) { minx = x-3; maxx = x+3; miny = y-3; maxy = y+3; }
289 else { minx = x-1; maxx = x+1; miny = y-1; maxy = y+1; }
291 if (minx < 0) minx=0; if (maxx > MAXX-1) maxx = MAXX-1;
292 if (miny < 0) miny=0; if (maxy > MAXY-1) maxy = MAXY-1;
294 for (j=miny; j<=maxy; j++)
295 for (n=minx; n<=maxx; n++)
296 if (know[n][j]==0)
298 cursor(n+1,j+1);
299 x=maxx; while (know[x][j]) --x;
300 for (i=n; i<=x; i++)
302 if ((l=mitem[i][j]) != 0) lprc(monstnamelist[l]);
303 else switch(l=item[i][j])
305 case OWALL: case 0: case OIVTELETRAP: case OTRAPARROWIV:
306 case OIVDARTRAP: case OIVTRAPDOOR:
307 lprc(objnamelist[l]); break;
309 default: setbold(); lprc(objnamelist[l]); resetbold();
311 know[i][j]=1;
313 n = maxx;
318 this routine shows only the spot that is given it. the spaces around
319 these coordinated are not shown
320 used in godirect() in monster.c for missile weapons display
322 void
323 show1cell(int x, int y)
325 if (c[BLINDCOUNT]) return; /* see nothing if blind */
326 cursor(x+1,y+1);
327 if ((k=mitem[x][y]) != 0) lprc(monstnamelist[k]);
328 else switch(k=item[x][y])
330 case OWALL: case 0: case OIVTELETRAP: case OTRAPARROWIV:
331 case OIVDARTRAP: case OIVTRAPDOOR:
332 lprc(objnamelist[k]); break;
334 default: setbold(); lprc(objnamelist[k]); resetbold();
336 know[x][y]|=1; /* we end up knowing about it */
340 showplayer()
342 subroutine to show where the player is on the screen
343 cursor values start from 1 up
345 void
346 showplayer(void)
348 cursor(playerx+1,playery+1);
349 oldx=playerx; oldy=playery;
353 moveplayer(dir)
355 subroutine to move the player from one room to another
356 returns 0 if can't move in that direction or hit a monster or on an object
357 else returns 1
358 nomove is set to 1 to stop the next move (inadvertent monsters hitting
359 players when walking into walls) if player walks off screen or into wall
361 short diroffx[] = { 0, 0, 1, 0, -1, 1, -1, 1, -1 };
362 short diroffy[] = { 0, 1, 0, -1, 0, -1, -1, 1, 1 };
365 moveplayer(int dir)
366 /* from = present room # direction = [1-north]
367 [2-east] [3-south] [4-west] [5-northeast]
368 [6-northwest] [7-southeast] [8-southwest]
369 if direction=0, don't move--just show where he is */
371 int l,n,i,j;
372 if (c[CONFUSE]) if (c[LEVEL]<rnd(30)) dir=rund(9); /*if confused any dir*/
373 l = playerx + diroffx[dir]; n = playery + diroffy[dir];
374 if (l<0 || l>=MAXX || n<0 || n>=MAXY) { nomove=1; return(yrepcount = 0); }
375 i = item[l][n]; j = mitem[l][n];
376 if (i==OWALL && c[WTW]==0) { nomove=1; return(yrepcount = 0); } /* hit a wall */
377 if (l==33 && n==MAXY-1 && level==1)
379 newcavelevel(0); for (l=0; l<MAXX; l++) for (n=0; n<MAXY; n++)
380 if (item[l][n]==OENTRANCE)
381 { playerx=l; playery=n; positionplayer(); drawscreen(); return(0); }
383 if (j>0) { hitmonster(l,n); return(yrepcount = 0); } /* hit a monster*/
384 lastpx = playerx; lastpy = playery;
385 playerx = l; playery = n;
386 if (i && i!=OTRAPARROWIV && i!=OIVTELETRAP && i!=OIVDARTRAP && i!=OIVTRAPDOOR) return(yrepcount = 0); else return(1);
390 * function to show what magic items have been discovered thus far
391 * enter with -1 for just spells, anything else will give scrolls & potions
393 static int lincount,count;
395 void
396 seemagic(int arg)
398 int i,number = 0;
399 count = lincount = 0; nosignal=1;
401 if (arg== -1) /* if display spells while casting one */
403 for (number=i=0; i<SPNUM; i++) if (spelknow[i]) number++;
404 number = (number+2)/3 + 4; /* # lines needed to display */
405 cl_up(79,number); cursor(1,1);
407 else
409 resetscroll(); clear();
412 lprcat("The magic spells you have discovered thus far:\n\n");
413 for (i=0; i<SPNUM; i++)
414 if (spelknow[i])
415 { lprintf("%s %-20s ",spelcode[i],spelname[i]); seepage(); }
417 if (arg== -1)
419 seepage(); more(); nosignal=0;
420 draws(0,MAXX,0,number); return;
423 lincount += 3; if (count!=0) { count=2; seepage(); }
425 lprcat("\nThe magic scrolls you have found to date are:\n\n");
426 count=0;
427 for (i=0; i<MAXSCROLL; i++)
428 if (scrollname[i][0])
429 if (scrollname[i][1]!=' ')
430 { lprintf("%-26s",&scrollname[i][1]); seepage(); }
432 lincount += 3; if (count!=0) { count=2; seepage(); }
434 lprcat("\nThe magic potions you have found to date are:\n\n");
435 count=0;
436 for (i=0; i<MAXPOTION; i++)
437 if (potionname[i][0])
438 if (potionname[i][1]!=' ')
439 { lprintf("%-26s",&potionname[i][1]); seepage(); }
441 if (lincount!=0) more(); nosignal=0; setscroll(); drawscreen();
445 * subroutine to paginate the seemagic function
447 static void
448 seepage(void)
450 if (++count==3)
452 lincount++; count=0; lprc('\n');
453 if (lincount>17) { lincount=0; more(); clear(); }