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