home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / games / larn / display.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-28  |  11.7 KB  |  435 lines

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