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 void bot_hpx(void);
8 static void bot_spellx(void);
9 static void botside(void);
10 static void botsub(int, const char *);
11 static void seepage(void);
13 static int minx
, maxx
, miny
, maxy
, k
, m
;
14 static char bot1f
= 0, bot2f
= 0, bot3f
= 0;
19 now for the bottom line of the display
44 bot3f
= bot1f
= bot2f
= 0;
62 if (cbak
[SPELLS
] <= -50 || (always
)) {
65 lprintf("Spells:%3d(%3d)", (long)c
[SPELLS
], (long)c
[SPELLMAX
]);
67 lprintf("Spells:%3d(%2d) ", (long)c
[SPELLS
], (long)c
[SPELLMAX
]);
68 lprintf(" AC: %-3d WC: %-3d Level", (long)c
[AC
], (long)c
[WCLASS
]);
70 lprintf("%3d", (long)c
[LEVEL
]);
72 lprintf(" %-2d", (long)c
[LEVEL
]);
73 lprintf(" Exp: %-9d %s\n", (long)c
[EXPERIENCE
], class[c
[LEVEL
] - 1]);
74 lprintf("HP: %3d(%3d) STR=%-2d INT=%-2d ",
75 (long)c
[HP
], (long)c
[HPMAX
], (long)(c
[STRENGTH
] + c
[STREXTRA
]), (long)c
[INTELLIGENCE
]);
76 lprintf("WIS=%-2d CON=%-2d DEX=%-2d CHA=%-2d LV:",
77 (long)c
[WISDOM
], (long)c
[CONSTITUTION
], (long)c
[DEXTERITY
], (long)c
[CHARISMA
]);
79 if ((level
== 0) || (wizard
))
84 lprcat(levelname
[(int)level
]);
85 lprintf(" Gold: %-6d", (long)c
[GOLD
]);
88 c
[TMP
] = c
[STRENGTH
] + c
[STREXTRA
];
89 for (i
= 0; i
< 100; i
++)
93 botsub(makecode(SPELLS
, 8, 18), "%3d");
95 botsub(makecode(SPELLMAX
, 12, 18), "%3d)");
97 botsub(makecode(SPELLMAX
, 12, 18), "%2d) ");
98 botsub(makecode(HP
, 5, 19), "%3d");
99 botsub(makecode(HPMAX
, 9, 19), "%3d");
100 botsub(makecode(AC
, 21, 18), "%-3d");
101 botsub(makecode(WCLASS
, 30, 18), "%-3d");
102 botsub(makecode(EXPERIENCE
, 49, 18), "%-9d");
103 if (c
[LEVEL
] != cbak
[LEVEL
]) {
105 lprcat(class[c
[LEVEL
] - 1]);
108 botsub(makecode(LEVEL
, 40, 18), "%3d");
110 botsub(makecode(LEVEL
, 40, 18), " %-2d");
111 c
[TMP
] = c
[STRENGTH
] + c
[STREXTRA
];
112 botsub(makecode(TMP
, 18, 19), "%-2d");
113 botsub(makecode(INTELLIGENCE
, 25, 19), "%-2d");
114 botsub(makecode(WISDOM
, 32, 19), "%-2d");
115 botsub(makecode(CONSTITUTION
, 39, 19), "%-2d");
116 botsub(makecode(DEXTERITY
, 46, 19), "%-2d");
117 botsub(makecode(CHARISMA
, 53, 19), "%-2d");
118 if ((level
!= cbak
[CAVELEVEL
]) || (c
[TELEFLAG
] != cbak
[TELEFLAG
])) {
119 if ((level
== 0) || (wizard
))
121 cbak
[TELEFLAG
] = c
[TELEFLAG
];
122 cbak
[CAVELEVEL
] = level
;
127 lprcat(levelname
[(int)level
]);
129 botsub(makecode(GOLD
, 69, 19), "%-6d");
134 special subroutine to update only the gold number on the bottomlines
140 botsub(makecode(GOLD
, 69, 19), "%-6d");
144 special routine to update hp and level fields on bottom lines
145 called in monster.c hitplayer() and spattack()
150 if (c
[EXPERIENCE
] != cbak
[EXPERIENCE
]) {
154 botsub(makecode(HP
, 5, 19), "%3d");
158 special routine to update number of spells called from regen()
163 botsub(makecode(SPELLS
, 9, 18), "%2d");
167 common subroutine for a more economical bottomline()
169 static struct bot_side_def
{
174 { STEALTH
, "stealth" },
175 { UNDEADPRO
, "undead pro" },
176 { SPIRITPRO
, "spirit pro" },
177 { CHARMCOUNT
, "Charm" },
178 { TIMESTOP
, "Time Stop" },
179 { HOLDMONST
, "Hold Monst" },
180 { GIANTSTR
, "Giant Str" },
181 { FIRERESISTANCE
, "Fire Resit" },
182 { DEXCOUNT
, "Dexterity" },
183 { STRCOUNT
, "Strength" },
184 { SCAREMONST
, "Scare" },
185 { HASTESELF
, "Haste Self" },
186 { CANCELLATION
, "Cancel" },
187 { INVISIBILITY
, "Invisible" },
188 { ALTPRO
, "Protect 3" },
189 { PROTECTIONTIME
, "Protect 2" },
197 for (i
= 0; i
< 17; i
++) {
198 idx
= bot_data
[i
].typ
;
199 if ((always
) || (c
[idx
] != cbak
[idx
])) {
200 if ((always
) || (cbak
[idx
] == 0)) {
203 lprcat(bot_data
[i
].string
);
205 } else if (c
[idx
] == 0) {
216 botsub(int idx
, const char *str
)
220 x
= (idx
>> 8) & 0xff;
222 if (c
[idx
] != cbak
[idx
]) {
225 lprintf(str
, (long)c
[idx
]);
230 * subroutine to draw only a section of the screen
231 * only the top section of the screen is updated.
232 * If entire lines are being drawn, then they will be cleared first.
234 /* for limited screen drawing */
235 int d_xmin
= 0, d_xmax
= MAXX
, d_ymin
= 0, d_ymax
= MAXY
;
238 draws(int xmin
, int xmax
, int ymin
, int ymax
)
241 /* clear section of screen as needed */
242 if (xmin
== 0 && xmax
== MAXX
) {
246 for (i
= ymin
; i
< ymin
; i
++)
250 d_xmin
= xmin
; /* for limited screen drawing */
255 /* draw stuff on right side of screen as needed */
256 if (xmin
<= 0 && xmax
== MAXX
) {
257 for (i
= ymin
; i
< ymax
; i
++) {
258 idx
= bot_data
[i
].typ
;
261 lprcat(bot_data
[i
].string
);
271 subroutine to redraw the whole screen as the player knows it
273 char screen
[MAXX
][MAXY
], d_flag
; /* template for the screen */
279 int lastx
, lasty
; /* variables used to optimize the object printing */
280 if (d_xmin
== 0 && d_xmax
== MAXX
&& d_ymin
== 0 && d_ymax
== MAXY
) {
282 clear(); /* clear the screen */
287 /* d_xmin=-1 means display all without bottomline */
291 for (i
= d_ymin
; i
< d_ymax
; i
++)
292 for (j
= d_xmin
; j
< d_xmax
; j
++)
295 else if ((l
= mitem
[j
][i
]) != 0)
296 screen
[j
][i
] = monstnamelist
[l
];
297 else if ((l
= item
[j
][i
]) == OWALL
)
302 for (i
= d_ymin
; i
< d_ymax
; i
++) {
304 while ((screen
[j
][i
] == ' ') && (j
< d_xmax
))
307 if (j
>= d_xmax
) /* don't search backwards if blank line */
309 else { /* search backwards for end of line */
311 while ((screen
[m
][i
] == ' ') && (m
> d_xmin
))
314 cursor(j
+ 1, i
+ 1);
320 for (l
= j
; l
<= j
+ 3; l
++)
321 if (screen
[l
][i
] != ' ')
324 while (screen
[j
][i
] == ' ' && j
<= m
)
326 cursor(j
+ 1, i
+ 1);
329 lprc(screen
[j
++][i
]);
332 setbold(); /* print out only bold objects now */
334 for (lastx
= lasty
= 127, i
= d_ymin
; i
< d_ymax
; i
++)
335 for (j
= d_xmin
; j
< d_xmax
; j
++) {
336 if ((l
= item
[j
][i
]) != 0)
338 if ((know
[j
][i
]) && (mitem
[j
][i
] == 0))
339 if (objnamelist
[l
] != ' ') {
340 if (lasty
!= i
+ 1 || lastx
!= j
)
341 cursor(lastx
= j
+ 1, lasty
= i
+ 1);
344 lprc(objnamelist
[l
]);
357 d_xmin
= 0, d_xmax
= MAXX
, d_ymin
= 0, d_ymax
= MAXY
; /* for limited screen drawing */
363 subroutine to display a cell location on the screen
366 showcell(int x
, int y
)
369 if (c
[BLINDCOUNT
]) /* see nothing if blind */
392 for (j
= miny
; j
<= maxy
; j
++)
393 for (n
= minx
; n
<= maxx
; n
++)
394 if (know
[n
][j
] == 0) {
395 cursor(n
+ 1, j
+ 1);
399 for (i
= n
; i
<= x
; i
++) {
400 if ((l
= mitem
[i
][j
]) != 0)
401 lprc(monstnamelist
[l
]);
403 switch (l
= item
[i
][j
]) {
410 lprc(objnamelist
[l
]);
415 lprc(objnamelist
[l
]);
425 this routine shows only the spot that is given it. the spaces around
426 these coordinated are not shown
427 used in godirect() in monster.c for missile weapons display
430 show1cell(int x
, int y
)
432 if (c
[BLINDCOUNT
]) /* see nothing if blind */
434 cursor(x
+ 1, y
+ 1);
435 if ((k
= mitem
[x
][y
]) != 0)
436 lprc(monstnamelist
[k
]);
438 switch (k
= item
[x
][y
]) {
445 lprc(objnamelist
[k
]);
450 lprc(objnamelist
[k
]);
453 know
[x
][y
] |= 1; /* we end up knowing about it */
459 subroutine to show where the player is on the screen
460 cursor values start from 1 up
465 cursor(playerx
+ 1, playery
+ 1);
473 subroutine to move the player from one room to another
474 returns 0 if can't move in that direction or hit a monster or on an object
476 nomove is set to 1 to stop the next move (inadvertent monsters hitting
477 players when walking into walls) if player walks off screen or into wall
479 short diroffx
[] = { 0, 0, 1, 0, -1, 1, -1, 1, -1 };
480 short diroffy
[] = { 0, 1, 0, -1, 0, -1, -1, 1, 1 };
483 * from = present room # direction = [1-north]
484 * [2-east] [3-south] [4-west] [5-northeast]
485 * [6-northwest] [7-southeast] [8-southwest]
486 * if direction=0, don't move--just show where he is
492 if (c
[CONFUSE
]) /*if confused any dir */
493 if (c
[LEVEL
] < rnd(30))
495 l
= playerx
+ diroffx
[dir
];
496 n
= playery
+ diroffy
[dir
];
497 if (l
< 0 || l
>= MAXX
|| n
< 0 || n
>= MAXY
) {
499 return (yrepcount
= 0);
504 if (i
== OWALL
&& c
[WTW
] == 0) {
506 return (yrepcount
= 0);
508 if (l
== 33 && n
== MAXY
- 1 && level
== 1) {
510 for (l
= 0; l
< MAXX
; l
++)
511 for (n
= 0; n
< MAXY
; n
++)
512 if (item
[l
][n
] == OENTRANCE
) {
523 return (yrepcount
= 0);
529 if (i
&& i
!= OTRAPARROWIV
&& i
!= OIVTELETRAP
&& i
!= OIVDARTRAP
&& i
!= OIVTRAPDOOR
)
530 return (yrepcount
= 0);
536 * function to show what magic items have been discovered thus far
537 * enter with -1 for just spells, anything else will give scrolls & potions
539 static int lincount
, count
;
545 count
= lincount
= 0;
548 if (arg
== -1) { /* if display spells while casting one */
549 for (number
= i
= 0; i
< SPNUM
; i
++)
552 number
= (number
+ 2) / 3 + 4; /* # lines needed to display */
560 lprcat("The magic spells you have discovered thus far:\n\n");
561 for (i
= 0; i
< SPNUM
; i
++)
563 lprintf("%s %-20s ", spelcode
[i
], spelname
[i
]);
571 draws(0, MAXX
, 0, number
);
581 lprcat("\nThe magic scrolls you have found to date are:\n\n");
583 for (i
= 0; i
< MAXSCROLL
; i
++)
584 if (scrollname
[i
][0])
585 if (scrollname
[i
][1] != ' ') {
586 lprintf("%-26s", &scrollname
[i
][1]);
596 lprcat("\nThe magic potions you have found to date are:\n\n");
598 for (i
= 0; i
< MAXPOTION
; i
++)
599 if (potionname
[i
][0])
600 if (potionname
[i
][1] != ' ') {
601 lprintf("%-26s", &potionname
[i
][1]);
613 * subroutine to paginate the seemagic function