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