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 $ */
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;
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);
20 now for the bottom line of the display
24 { recalc(); bot1f
=1; }
34 if (bot1f
) { bot3f
=bot1f
=bot2f
=0; bot_linex(); return; }
35 if (bot2f
) { bot2f
=0; bot_hpx(); }
36 if (bot3f
) { bot3f
=0; bot_spellx(); }
43 if (cbak
[SPELLS
] <= -50 || (always
))
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
]);
61 c
[TMP
] = c
[STRENGTH
]+c
[STREXTRA
];
62 for (i
=0; i
<100; i
++) cbak
[i
]=c
[i
];
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");
96 special subroutine to update only the gold number on the bottomlines
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()
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()
125 botsub(makecode(SPELLS
,9,18),"%2d");
129 common subroutine for a more economical bottomline()
131 static struct bot_side_def
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"}
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(" "); }
165 botsub(int idx
, const char *str
)
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 */
181 draws(int xmin
, int xmax
, int ymin
, int ymax
)
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);
190 d_xmin
=xmin
; d_xmax
=xmax
; d_ymin
=ymin
; d_ymax
=ymax
; /* for limited screen drawing */
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
;
199 cursor(70,i
+1); lprcat(bot_data
[i
].string
);
209 subroutine to redraw the whole screen as the player knows it
211 char screen
[MAXX
][MAXY
],d_flag
; /* template for the screen */
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 */
224 d_flag
=0; cursor(1,1);
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
++;
240 if (j
>= d_xmax
) m
=d_xmin
; /* don't search backwards if blank line */
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;
250 for (l
=j
; l
<=j
+3; l
++) if (screen
[l
][i
] != ' ') 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
++)
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(); }
275 d_xmin
= 0 , d_xmax
= MAXX
, d_ymin
= 0 , d_ymax
= MAXY
; /* for limited screen drawing */
281 subroutine to display a cell location on the screen
284 showcell(int x
, int y
)
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
++)
299 x
=maxx
; while (know
[x
][j
]) --x
;
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();
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
323 show1cell(int x
, int y
)
325 if (c
[BLINDCOUNT
]) return; /* see nothing if blind */
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 */
342 subroutine to show where the player is on the screen
343 cursor values start from 1 up
348 cursor(playerx
+1,playery
+1);
349 oldx
=playerx
; oldy
=playery
;
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
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 };
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 */
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
;
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);
409 resetscroll(); clear();
412 lprcat("The magic spells you have discovered thus far:\n\n");
413 for (i
=0; i
<SPNUM
; i
++)
415 { lprintf("%s %-20s ",spelcode
[i
],spelname
[i
]); seepage(); }
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");
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");
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
452 lincount
++; count
=0; lprc('\n');
453 if (lincount
>17) { lincount
=0; more(); clear(); }