136982Sbostic /* display.c Larn is copyrighted 1986 by Noah Morgan. */
236982Sbostic #include "header.h"
336982Sbostic #define makecode(_a,_b,_c) (((_a)<<16) + ((_b)<<8) + (_c))
436982Sbostic
536982Sbostic static int minx,maxx,miny,maxy,k,m;
636982Sbostic static char bot1f=0,bot2f=0,bot3f=0;
736982Sbostic char always=0;
836982Sbostic /*
936982Sbostic bottomline()
1036982Sbostic
1136982Sbostic now for the bottom line of the display
1236982Sbostic */
bottomline()1336982Sbostic bottomline()
1436982Sbostic { recalc(); bot1f=1; }
bottomhp()1536982Sbostic bottomhp()
1636982Sbostic { bot2f=1; }
bottomspell()1736982Sbostic bottomspell()
1836982Sbostic { bot3f=1; }
bottomdo()1936982Sbostic bottomdo()
2036982Sbostic {
2136982Sbostic if (bot1f) { bot3f=bot1f=bot2f=0; bot_linex(); return; }
2236982Sbostic if (bot2f) { bot2f=0; bot_hpx(); }
2336982Sbostic if (bot3f) { bot3f=0; bot_spellx(); }
2436982Sbostic }
2536982Sbostic
26*46749Sbostic static void botsub();
27*46749Sbostic
bot_linex()2836982Sbostic bot_linex()
2936982Sbostic {
3036982Sbostic register int i;
3136982Sbostic if (cbak[SPELLS] <= -50 || (always))
3236982Sbostic {
3336982Sbostic cursor( 1,18);
3436982Sbostic if (c[SPELLMAX]>99) lprintf("Spells:%3d(%3d)",(long)c[SPELLS],(long)c[SPELLMAX]);
3536982Sbostic else lprintf("Spells:%3d(%2d) ",(long)c[SPELLS],(long)c[SPELLMAX]);
3636982Sbostic lprintf(" AC: %-3d WC: %-3d Level",(long)c[AC],(long)c[WCLASS]);
3736982Sbostic if (c[LEVEL]>99) lprintf("%3d",(long)c[LEVEL]);
3836982Sbostic else lprintf(" %-2d",(long)c[LEVEL]);
3936982Sbostic lprintf(" Exp: %-9d %s\n",(long)c[EXPERIENCE],class[c[LEVEL]-1]);
4036982Sbostic lprintf("HP: %3d(%3d) STR=%-2d INT=%-2d ",
4136982Sbostic (long)c[HP],(long)c[HPMAX],(long)(c[STRENGTH]+c[STREXTRA]),(long)c[INTELLIGENCE]);
4236982Sbostic lprintf("WIS=%-2d CON=%-2d DEX=%-2d CHA=%-2d LV:",
4336982Sbostic (long)c[WISDOM],(long)c[CONSTITUTION],(long)c[DEXTERITY],(long)c[CHARISMA]);
4436982Sbostic
4536982Sbostic if ((level==0) || (wizard)) c[TELEFLAG]=0;
4636982Sbostic if (c[TELEFLAG]) lprcat(" ?"); else lprcat(levelname[level]);
4736982Sbostic lprintf(" Gold: %-6d",(long)c[GOLD]);
4836982Sbostic always=1; botside();
4936982Sbostic c[TMP] = c[STRENGTH]+c[STREXTRA];
5036982Sbostic for (i=0; i<100; i++) cbak[i]=c[i];
5136982Sbostic return;
5236982Sbostic }
5336982Sbostic
5436982Sbostic botsub(makecode(SPELLS,8,18),"%3d");
5536982Sbostic if (c[SPELLMAX]>99) botsub(makecode(SPELLMAX,12,18),"%3d)");
5636982Sbostic else botsub(makecode(SPELLMAX,12,18),"%2d) ");
5736982Sbostic botsub(makecode(HP,5,19),"%3d");
5836982Sbostic botsub(makecode(HPMAX,9,19),"%3d");
5936982Sbostic botsub(makecode(AC,21,18),"%-3d");
6036982Sbostic botsub(makecode(WCLASS,30,18),"%-3d");
6136982Sbostic botsub(makecode(EXPERIENCE,49,18),"%-9d");
6236982Sbostic if (c[LEVEL] != cbak[LEVEL])
6336982Sbostic { cursor(59,18); lprcat(class[c[LEVEL]-1]); }
6436982Sbostic if (c[LEVEL]>99) botsub(makecode(LEVEL,40,18),"%3d");
6536982Sbostic else botsub(makecode(LEVEL,40,18)," %-2d");
6636982Sbostic c[TMP] = c[STRENGTH]+c[STREXTRA]; botsub(makecode(TMP,18,19),"%-2d");
6736982Sbostic botsub(makecode(INTELLIGENCE,25,19),"%-2d");
6836982Sbostic botsub(makecode(WISDOM,32,19),"%-2d");
6936982Sbostic botsub(makecode(CONSTITUTION,39,19),"%-2d");
7036982Sbostic botsub(makecode(DEXTERITY,46,19),"%-2d");
7136982Sbostic botsub(makecode(CHARISMA,53,19),"%-2d");
7236982Sbostic if ((level != cbak[CAVELEVEL]) || (c[TELEFLAG] != cbak[TELEFLAG]))
7336982Sbostic {
7436982Sbostic if ((level==0) || (wizard)) c[TELEFLAG]=0;
7536982Sbostic cbak[TELEFLAG] = c[TELEFLAG];
7636982Sbostic cbak[CAVELEVEL] = level; cursor(59,19);
7736982Sbostic if (c[TELEFLAG]) lprcat(" ?"); else lprcat(levelname[level]);
7836982Sbostic }
7936982Sbostic botsub(makecode(GOLD,69,19),"%-6d");
8036982Sbostic botside();
8136982Sbostic }
8236982Sbostic
8336982Sbostic /*
8436982Sbostic special subroutine to update only the gold number on the bottomlines
8536982Sbostic called from ogold()
8636982Sbostic */
bottomgold()8736982Sbostic bottomgold()
8836982Sbostic {
8936982Sbostic botsub(makecode(GOLD,69,19),"%-6d");
9036982Sbostic /* botsub(GOLD,"%-6d",69,19); */
9136982Sbostic }
9236982Sbostic
9336982Sbostic /*
9436982Sbostic special routine to update hp and level fields on bottom lines
9536982Sbostic called in monster.c hitplayer() and spattack()
9636982Sbostic */
bot_hpx()9736982Sbostic bot_hpx()
9836982Sbostic {
9936982Sbostic if (c[EXPERIENCE] != cbak[EXPERIENCE])
10036982Sbostic {
10136982Sbostic recalc(); bot_linex();
10236982Sbostic }
10336982Sbostic else botsub(makecode(HP,5,19),"%3d");
10436982Sbostic }
10536982Sbostic
10636982Sbostic /*
10736982Sbostic special routine to update number of spells called from regen()
10836982Sbostic */
bot_spellx()10936982Sbostic bot_spellx()
11036982Sbostic {
11136982Sbostic botsub(makecode(SPELLS,9,18),"%2d");
11236982Sbostic }
11336982Sbostic
11436982Sbostic /*
11536982Sbostic common subroutine for a more economical bottomline()
11636982Sbostic */
11736982Sbostic static struct bot_side_def
11836982Sbostic {
11936982Sbostic int typ;
12036982Sbostic char *string;
12136982Sbostic }
12236982Sbostic bot_data[] =
12336982Sbostic {
12436982Sbostic STEALTH,"stealth", UNDEADPRO,"undead pro", SPIRITPRO,"spirit pro",
12536982Sbostic CHARMCOUNT,"Charm", TIMESTOP,"Time Stop", HOLDMONST,"Hold Monst",
12636982Sbostic GIANTSTR,"Giant Str", FIRERESISTANCE,"Fire Resit", DEXCOUNT,"Dexterity",
12736982Sbostic STRCOUNT,"Strength", SCAREMONST,"Scare", HASTESELF,"Haste Self",
12836982Sbostic CANCELLATION,"Cancel", INVISIBILITY,"Invisible", ALTPRO,"Protect 3",
12936982Sbostic PROTECTIONTIME,"Protect 2", WTW,"Wall-Walk"
13036982Sbostic };
13136982Sbostic
botside()13236982Sbostic botside()
13336982Sbostic {
13436982Sbostic register int i,idx;
13536982Sbostic for (i=0; i<17; i++)
13636982Sbostic {
13736982Sbostic idx = bot_data[i].typ;
13836982Sbostic if ((always) || (c[idx] != cbak[idx]))
13936982Sbostic {
14036982Sbostic if ((always) || (cbak[idx] == 0))
14136982Sbostic { if (c[idx]) { cursor(70,i+1); lprcat(bot_data[i].string); } } else
14236982Sbostic if (c[idx]==0) { cursor(70,i+1); lprcat(" "); }
14336982Sbostic cbak[idx]=c[idx];
14436982Sbostic }
14536982Sbostic }
14636982Sbostic always=0;
14736982Sbostic }
14836982Sbostic
149*46749Sbostic static void
botsub(idx,str)150*46749Sbostic botsub(idx,str)
15136982Sbostic register int idx;
15236982Sbostic char *str;
15336982Sbostic {
15436982Sbostic register int x,y;
15536982Sbostic y = idx & 0xff; x = (idx>>8) & 0xff; idx >>= 16;
15636982Sbostic if (c[idx] != cbak[idx])
15736982Sbostic { cbak[idx]=c[idx]; cursor(x,y); lprintf(str,(long)c[idx]); }
15836982Sbostic }
15936982Sbostic
16036982Sbostic /*
16136982Sbostic * subroutine to draw only a section of the screen
16236982Sbostic * only the top section of the screen is updated. If entire lines are being
16336982Sbostic * drawn, then they will be cleared first.
16436982Sbostic */
16536982Sbostic int d_xmin=0,d_xmax=MAXX,d_ymin=0,d_ymax=MAXY; /* for limited screen drawing */
draws(xmin,xmax,ymin,ymax)16636982Sbostic draws(xmin,xmax,ymin,ymax)
16736982Sbostic int xmin,xmax,ymin,ymax;
16836982Sbostic {
16936982Sbostic register int i,idx;
17036982Sbostic if (xmin==0 && xmax==MAXX) /* clear section of screen as needed */
17136982Sbostic {
17236982Sbostic if (ymin==0) cl_up(79,ymax);
17336982Sbostic else for (i=ymin; i<ymin; i++) cl_line(1,i+1);
17436982Sbostic xmin = -1;
17536982Sbostic }
17636982Sbostic d_xmin=xmin; d_xmax=xmax; d_ymin=ymin; d_ymax=ymax; /* for limited screen drawing */
17736982Sbostic drawscreen();
17836982Sbostic if (xmin<=0 && xmax==MAXX) /* draw stuff on right side of screen as needed*/
17936982Sbostic {
18036982Sbostic for (i=ymin; i<ymax; i++)
18136982Sbostic {
18236982Sbostic idx = bot_data[i].typ;
18336982Sbostic if (c[idx])
18436982Sbostic {
18536982Sbostic cursor(70,i+1); lprcat(bot_data[i].string);
18636982Sbostic }
18736982Sbostic cbak[idx]=c[idx];
18836982Sbostic }
18936982Sbostic }
19036982Sbostic }
19136982Sbostic
19236982Sbostic /*
19336982Sbostic drawscreen()
19436982Sbostic
19536982Sbostic subroutine to redraw the whole screen as the player knows it
19636982Sbostic */
19736982Sbostic char screen[MAXX][MAXY],d_flag; /* template for the screen */
drawscreen()19836982Sbostic drawscreen()
19936982Sbostic {
20036982Sbostic register int i,j,k;
20136982Sbostic int lastx,lasty; /* variables used to optimize the object printing */
20236982Sbostic if (d_xmin==0 && d_xmax==MAXX && d_ymin==0 && d_ymax==MAXY)
20336982Sbostic {
20436982Sbostic d_flag=1; clear(); /* clear the screen */
20536982Sbostic }
20636982Sbostic else
20736982Sbostic {
20836982Sbostic d_flag=0; cursor(1,1);
20936982Sbostic }
21036982Sbostic if (d_xmin<0)
21136982Sbostic d_xmin=0; /* d_xmin=-1 means display all without bottomline */
21236982Sbostic
21336982Sbostic for (i=d_ymin; i<d_ymax; i++)
21436982Sbostic for (j=d_xmin; j<d_xmax; j++)
21536982Sbostic if (know[j][i]==0) screen[j][i] = ' '; else
21636982Sbostic if (k=mitem[j][i]) screen[j][i] = monstnamelist[k]; else
21736982Sbostic if ((k=item[j][i])==OWALL) screen[j][i] = '#';
21836982Sbostic else screen[j][i] = ' ';
21936982Sbostic
22036982Sbostic for (i=d_ymin; i<d_ymax; i++)
22136982Sbostic {
22236982Sbostic j=d_xmin; while ((screen[j][i]==' ') && (j<d_xmax)) j++;
22336982Sbostic /* was m=0 */
22436982Sbostic if (j >= d_xmax) m=d_xmin; /* don't search backwards if blank line */
22536982Sbostic else
22636982Sbostic { /* search backwards for end of line */
22736982Sbostic m=d_xmax-1; while ((screen[m][i]==' ') && (m>d_xmin)) --m;
22836982Sbostic if (j<=m) cursor(j+1,i+1); else continue;
22936982Sbostic }
23036982Sbostic while (j <= m)
23136982Sbostic {
23236982Sbostic if (j <= m-3)
23336982Sbostic {
23436982Sbostic for (k=j; k<=j+3; k++) if (screen[k][i] != ' ') k=1000;
23536982Sbostic if (k < 1000)
23636982Sbostic { while(screen[j][i]==' ' && j<=m) j++; cursor(j+1,i+1); }
23736982Sbostic }
23836982Sbostic lprc(screen[j++][i]);
23936982Sbostic }
24036982Sbostic }
24136982Sbostic setbold(); /* print out only bold objects now */
24236982Sbostic
24336982Sbostic for (lastx=lasty=127, i=d_ymin; i<d_ymax; i++)
24436982Sbostic for (j=d_xmin; j<d_xmax; j++)
24536982Sbostic {
24636982Sbostic if (k=item[j][i])
24736982Sbostic if (k != OWALL)
24836982Sbostic if ((know[j][i]) && (mitem[j][i]==0))
24936982Sbostic if (objnamelist[k]!=' ')
25036982Sbostic {
25136982Sbostic if (lasty!=i+1 || lastx!=j)
25236982Sbostic cursor(lastx=j+1,lasty=i+1); else lastx++;
25336982Sbostic lprc(objnamelist[k]);
25436982Sbostic }
25536982Sbostic }
25636982Sbostic
25736982Sbostic resetbold(); if (d_flag) { always=1; botside(); always=1; bot_linex(); }
25836982Sbostic oldx=99;
25936982Sbostic d_xmin = 0 , d_xmax = MAXX , d_ymin = 0 , d_ymax = MAXY; /* for limited screen drawing */
26036982Sbostic }
26136982Sbostic
26236982Sbostic /*
26336982Sbostic showcell(x,y)
26436982Sbostic
26536982Sbostic subroutine to display a cell location on the screen
26636982Sbostic */
showcell(x,y)26736982Sbostic showcell(x,y)
26836982Sbostic int x,y;
26936982Sbostic {
27036982Sbostic register int i,j,k,m;
27136982Sbostic if (c[BLINDCOUNT]) return; /* see nothing if blind */
27236982Sbostic if (c[AWARENESS]) { minx = x-3; maxx = x+3; miny = y-3; maxy = y+3; }
27336982Sbostic else { minx = x-1; maxx = x+1; miny = y-1; maxy = y+1; }
27436982Sbostic
27536982Sbostic if (minx < 0) minx=0; if (maxx > MAXX-1) maxx = MAXX-1;
27636982Sbostic if (miny < 0) miny=0; if (maxy > MAXY-1) maxy = MAXY-1;
27736982Sbostic
27836982Sbostic for (j=miny; j<=maxy; j++)
27936982Sbostic for (m=minx; m<=maxx; m++)
28036982Sbostic if (know[m][j]==0)
28136982Sbostic {
28236982Sbostic cursor(m+1,j+1);
28336982Sbostic x=maxx; while (know[x][j]) --x;
28436982Sbostic for (i=m; i<=x; i++)
28536982Sbostic {
28636982Sbostic if ((k=mitem[i][j]) != 0) lprc(monstnamelist[k]);
28736982Sbostic else switch(k=item[i][j])
28836982Sbostic {
28936982Sbostic case OWALL: case 0: case OIVTELETRAP: case OTRAPARROWIV:
29036982Sbostic case OIVDARTRAP: case OIVTRAPDOOR:
29136982Sbostic lprc(objnamelist[k]); break;
29236982Sbostic
29336982Sbostic default: setbold(); lprc(objnamelist[k]); resetbold();
29436982Sbostic };
29536982Sbostic know[i][j]=1;
29636982Sbostic }
29736982Sbostic m = maxx;
29836982Sbostic }
29936982Sbostic }
30036982Sbostic
30136982Sbostic /*
30236982Sbostic this routine shows only the spot that is given it. the spaces around
30336982Sbostic these coordinated are not shown
30436982Sbostic used in godirect() in monster.c for missile weapons display
30536982Sbostic */
show1cell(x,y)30636982Sbostic show1cell(x,y)
30736982Sbostic int x,y;
30836982Sbostic {
30936982Sbostic if (c[BLINDCOUNT]) return; /* see nothing if blind */
31036982Sbostic cursor(x+1,y+1);
31136982Sbostic if ((k=mitem[x][y]) != 0) lprc(monstnamelist[k]);
31236982Sbostic else switch(k=item[x][y])
31336982Sbostic {
31436982Sbostic case OWALL: case 0: case OIVTELETRAP: case OTRAPARROWIV:
31536982Sbostic case OIVDARTRAP: case OIVTRAPDOOR:
31636982Sbostic lprc(objnamelist[k]); break;
31736982Sbostic
31836982Sbostic default: setbold(); lprc(objnamelist[k]); resetbold();
31936982Sbostic };
32036982Sbostic know[x][y]|=1; /* we end up knowing about it */
32136982Sbostic }
32236982Sbostic
32336982Sbostic /*
32436982Sbostic showplayer()
32536982Sbostic
32636982Sbostic subroutine to show where the player is on the screen
32736982Sbostic cursor values start from 1 up
32836982Sbostic */
showplayer()32936982Sbostic showplayer()
33036982Sbostic {
33136982Sbostic cursor(playerx+1,playery+1);
33236982Sbostic oldx=playerx; oldy=playery;
33336982Sbostic }
33436982Sbostic
33536982Sbostic /*
33636982Sbostic moveplayer(dir)
33736982Sbostic
33836982Sbostic subroutine to move the player from one room to another
33936982Sbostic returns 0 if can't move in that direction or hit a monster or on an object
34036982Sbostic else returns 1
34136982Sbostic nomove is set to 1 to stop the next move (inadvertent monsters hitting
34236982Sbostic players when walking into walls) if player walks off screen or into wall
34336982Sbostic */
34436982Sbostic short diroffx[] = { 0, 0, 1, 0, -1, 1, -1, 1, -1 };
34536982Sbostic short diroffy[] = { 0, 1, 0, -1, 0, -1, -1, 1, 1 };
moveplayer(dir)34636982Sbostic moveplayer(dir)
34736982Sbostic int dir; /* from = present room # direction = [1-north]
34836982Sbostic [2-east] [3-south] [4-west] [5-northeast]
34936982Sbostic [6-northwest] [7-southeast] [8-southwest]
35036982Sbostic if direction=0, don't move--just show where he is */
35136982Sbostic {
35236982Sbostic register int k,m,i,j;
35336982Sbostic if (c[CONFUSE]) if (c[LEVEL]<rnd(30)) dir=rund(9); /*if confused any dir*/
35436982Sbostic k = playerx + diroffx[dir]; m = playery + diroffy[dir];
35536982Sbostic if (k<0 || k>=MAXX || m<0 || m>=MAXY) { nomove=1; return(yrepcount = 0); }
35636982Sbostic i = item[k][m]; j = mitem[k][m];
35736982Sbostic if (i==OWALL && c[WTW]==0) { nomove=1; return(yrepcount = 0); } /* hit a wall */
35836982Sbostic if (k==33 && m==MAXY-1 && level==1)
35936982Sbostic {
36036982Sbostic newcavelevel(0); for (k=0; k<MAXX; k++) for (m=0; m<MAXY; m++)
36136982Sbostic if (item[k][m]==OENTRANCE)
36236982Sbostic { playerx=k; playery=m; positionplayer(); drawscreen(); return(0); }
36336982Sbostic }
36436982Sbostic if (j>0) { hitmonster(k,m); return(yrepcount = 0); } /* hit a monster*/
36536982Sbostic lastpx = playerx; lastpy = playery;
36636982Sbostic playerx = k; playery = m;
36736982Sbostic if (i && i!=OTRAPARROWIV && i!=OIVTELETRAP && i!=OIVDARTRAP && i!=OIVTRAPDOOR) return(yrepcount = 0); else return(1);
36836982Sbostic }
36936982Sbostic
37036982Sbostic /*
37136982Sbostic * function to show what magic items have been discovered thus far
37236982Sbostic * enter with -1 for just spells, anything else will give scrolls & potions
37336982Sbostic */
37436982Sbostic static int lincount,count;
seemagic(arg)37536982Sbostic seemagic(arg)
37636982Sbostic int arg;
37736982Sbostic {
37836982Sbostic register int i,number;
37936982Sbostic count = lincount = 0; nosignal=1;
38036982Sbostic
38136982Sbostic if (arg== -1) /* if display spells while casting one */
38236982Sbostic {
38336982Sbostic for (number=i=0; i<SPNUM; i++) if (spelknow[i]) number++;
38436982Sbostic number = (number+2)/3 + 4; /* # lines needed to display */
38536982Sbostic cl_up(79,number); cursor(1,1);
38636982Sbostic }
38736982Sbostic else
38836982Sbostic {
38936982Sbostic resetscroll(); clear();
39036982Sbostic }
39136982Sbostic
39236982Sbostic lprcat("The magic spells you have discovered thus far:\n\n");
39336982Sbostic for (i=0; i<SPNUM; i++)
39436982Sbostic if (spelknow[i])
39536982Sbostic { lprintf("%s %-20s ",spelcode[i],spelname[i]); seepage(); }
39636982Sbostic
39736982Sbostic if (arg== -1)
39836982Sbostic {
39936982Sbostic seepage(); more(); nosignal=0;
40036982Sbostic draws(0,MAXX,0,number); return;
40136982Sbostic }
40236982Sbostic
40336982Sbostic lincount += 3; if (count!=0) { count=2; seepage(); }
40436982Sbostic
40536982Sbostic lprcat("\nThe magic scrolls you have found to date are:\n\n");
40636982Sbostic count=0;
40736982Sbostic for (i=0; i<MAXSCROLL; i++)
40836982Sbostic if (scrollname[i][0])
40936982Sbostic if (scrollname[i][1]!=' ')
41036982Sbostic { lprintf("%-26s",&scrollname[i][1]); seepage(); }
41136982Sbostic
41236982Sbostic lincount += 3; if (count!=0) { count=2; seepage(); }
41336982Sbostic
41436982Sbostic lprcat("\nThe magic potions you have found to date are:\n\n");
41536982Sbostic count=0;
41636982Sbostic for (i=0; i<MAXPOTION; i++)
41736982Sbostic if (potionname[i][0])
41836982Sbostic if (potionname[i][1]!=' ')
41936982Sbostic { lprintf("%-26s",&potionname[i][1]); seepage(); }
42036982Sbostic
42136982Sbostic if (lincount!=0) more(); nosignal=0; setscroll(); drawscreen();
42236982Sbostic }
42336982Sbostic
42436982Sbostic /*
42536982Sbostic * subroutine to paginate the seemagic function
42636982Sbostic */
seepage()42736982Sbostic seepage()
42836982Sbostic {
42936982Sbostic if (++count==3)
43036982Sbostic {
43136982Sbostic lincount++; count=0; lprc('\n');
43236982Sbostic if (lincount>17) { lincount=0; more(); clear(); }
43336982Sbostic }
43436982Sbostic }
435