games: Massive style(9) cleanup commit. Reduces differences to NetBSD.
[dragonfly.git] / games / hunt / huntd / draw.c
blob7d6aa2f9a846ea3de021a64db010e343f180d4b4
1 /*-
2 * Copyright (c) 1983-2003, Regents of the University of California.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University of California, San Francisco nor
15 * the names of its contributors may be used to endorse or promote
16 * products derived from this software without specific prior written
17 * permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * $OpenBSD: draw.c,v 1.7 2003/06/11 08:45:33 pjanzen Exp $
32 * $NetBSD: draw.c,v 1.2 1997/10/10 16:33:04 lukem Exp $
33 * $DragonFly: src/games/hunt/huntd/draw.c,v 1.2 2008/09/04 16:12:51 swildner Exp $
36 #include <string.h>
38 #include "hunt.h"
39 #include "server.h"
40 #include "conf.h"
42 static char translate(char);
43 static int player_sym(PLAYER *, int, int);
44 static void drawstatus(PLAYER *);
45 static void see(PLAYER *, int);
48 * drawmaze:
49 * Draw the entire maze on a player's screen.
51 void
52 drawmaze(PLAYER *pp)
54 int x;
55 char *sp;
56 int y;
57 char *endp;
59 /* Clear the client's screen: */
60 clrscr(pp);
61 /* Draw the top row of the maze: */
62 outstr(pp, pp->p_maze[0], WIDTH);
63 for (y = 1; y < HEIGHT - 1; y++) {
64 endp = &pp->p_maze[y][WIDTH];
65 for (x = 0, sp = pp->p_maze[y]; sp < endp; x++, sp++)
66 if (*sp != SPACE) {
67 cgoto(pp, y, x);
68 /* Draw the player as themselves */
69 if (pp->p_x == x && pp->p_y == y)
70 outch(pp, translate(*sp));
71 /* Possibly draw other players as team nrs */
72 else if (is_player(*sp))
73 outch(pp, player_sym(pp, y, x));
74 else
75 outch(pp, *sp);
78 /* Draw the last row of the maze: */
79 cgoto(pp, HEIGHT - 1, 0);
80 outstr(pp, pp->p_maze[HEIGHT - 1], WIDTH);
81 drawstatus(pp);
85 * drawstatus - put up the status lines (this assumes the screen
86 * size is 80x24 with the maze being 64x24)
88 static void
89 drawstatus(PLAYER *pp)
91 int i;
92 PLAYER *np;
94 outyx(pp, STAT_AMMO_ROW, STAT_LABEL_COL, "Ammo:");
95 ammo_update(pp);
97 outyx(pp, STAT_GUN_ROW, STAT_LABEL_COL, "Gun:");
98 outyx(pp, STAT_GUN_ROW, STAT_VALUE_COL, "%3s",
99 (pp->p_ncshot < conf_maxncshot) ? "ok" : "");
101 outyx(pp, STAT_DAM_ROW, STAT_LABEL_COL, "Damage:");
102 outyx(pp, STAT_DAM_ROW, STAT_VALUE_COL, "%2d/%2d",
103 pp->p_damage, pp->p_damcap);
105 outyx(pp, STAT_KILL_ROW, STAT_LABEL_COL, "Kills:");
106 outyx(pp, STAT_KILL_ROW, STAT_VALUE_COL, "%3d",
107 (pp->p_damcap - conf_maxdam) / 2);
109 outyx(pp, STAT_PLAY_ROW, STAT_LABEL_COL, "Player:");
110 for (i = STAT_PLAY_ROW + 1, np = Player; np < End_player; np++, i++) {
111 outyx(pp, i, STAT_NAME_COL, "%5.2f%c%-10.10s %c",
112 np->p_ident->i_score, stat_char(np),
113 np->p_ident->i_name, np->p_ident->i_team);
116 outyx(pp, STAT_MON_ROW, STAT_LABEL_COL, "Monitor:");
117 for (i = STAT_MON_ROW + 1, np = Monitor; np < End_monitor; np++, i++) {
118 outyx(pp, i++, STAT_NAME_COL, "%5.5s %-10.10s %c",
119 " ", np->p_ident->i_name, np->p_ident->i_team);
124 * look
125 * check and update the visible area around the player
127 void
128 look(PLAYER *pp)
130 int x, y;
132 x = pp->p_x;
133 y = pp->p_y;
136 * The player is aware of all objects immediately adjacent to
137 * their position:
139 check(pp, y - 1, x - 1);
140 check(pp, y - 1, x );
141 check(pp, y - 1, x + 1);
142 check(pp, y , x - 1);
143 check(pp, y , x );
144 check(pp, y , x + 1);
145 check(pp, y + 1, x - 1);
146 check(pp, y + 1, x );
147 check(pp, y + 1, x + 1);
149 switch (pp->p_face) {
150 /* The player can see down corridors in directions except behind: */
151 case LEFTS:
152 see(pp, LEFTS);
153 see(pp, ABOVE);
154 see(pp, BELOW);
155 break;
156 case RIGHT:
157 see(pp, RIGHT);
158 see(pp, ABOVE);
159 see(pp, BELOW);
160 break;
161 case ABOVE:
162 see(pp, ABOVE);
163 see(pp, LEFTS);
164 see(pp, RIGHT);
165 break;
166 case BELOW:
167 see(pp, BELOW);
168 see(pp, LEFTS);
169 see(pp, RIGHT);
170 break;
171 /* But they don't see too far when they are flying about: */
172 case FLYER:
173 break;
176 /* Move the cursor back over the player: */
177 cgoto(pp, y, x);
181 * see
182 * Look down a corridor, or towards an open space. This
183 * is a simulation of visibility from the player's perspective.
185 static void
186 see(PLAYER *pp, int face)
188 char *sp;
189 int y, x;
191 /* Start from the player's position: */
192 x = pp->p_x;
193 y = pp->p_y;
195 #define seewalk(dx, dy) \
196 x += (dx); \
197 y += (dy); \
198 sp = &Maze[y][x]; \
199 while (See_over[(int)*sp]) { \
200 x += (dx); \
201 y += (dy); \
202 sp += ((dx) + (dy) * sizeof Maze[0]); \
203 check(pp, y + dx, x + dy); \
204 check(pp, y, x); \
205 check(pp, y - dx, x - dy); \
208 switch (face) {
209 case LEFTS:
210 seewalk(-1, 0); break;
211 case RIGHT:
212 seewalk(1, 0); break;
213 case ABOVE:
214 seewalk(0, -1); break;
215 case BELOW:
216 seewalk(0, 1); break;
221 * check
222 * The player is aware of a cell in the maze.
223 * Ensure it is shown properly on their screen.
225 void
226 check(PLAYER *pp, int y, int x)
228 int i;
229 int ch;
230 PLAYER *rpp;
232 if (pp == ALL_PLAYERS) {
233 for (pp = Player; pp < End_player; pp++)
234 check(pp, y, x);
235 for (pp = Monitor; pp < End_monitor; pp++)
236 check(pp, y, x);
237 return;
240 i = y * sizeof Maze[0] + x;
241 ch = ((char *) Maze)[i];
242 if (ch != ((char *) pp->p_maze)[i]) {
243 rpp = pp;
244 cgoto(rpp, y, x);
245 if (x == rpp->p_x && y == rpp->p_y)
246 outch(rpp, translate(ch));
247 else if (is_player(ch))
248 outch(rpp, player_sym(rpp, y, x));
249 else
250 outch(rpp, ch);
251 ((char *) rpp->p_maze)[i] = ch;
256 * showstat
257 * Update the status of a player on everyone's screen
259 void
260 showstat(PLAYER *pp)
263 outyx(ALL_PLAYERS,
264 STAT_PLAY_ROW + 1 + (pp - Player), STAT_SCAN_COL,
265 "%c", stat_char(pp));
269 * drawplayer:
270 * Draw the player on the screen and show him to everyone who's scanning
271 * unless he is cloaked.
272 * The 'draw' flag when false, causes the 'saved under' character to
273 * be drawn instead of the player; effectively un-drawing the player.
275 void
276 drawplayer(PLAYER *pp, FLAG draw)
278 PLAYER *newp;
279 int x, y;
281 x = pp->p_x;
282 y = pp->p_y;
284 /* Draw or un-draw the player into the master map: */
285 Maze[y][x] = draw ? pp->p_face : pp->p_over;
287 /* The monitors can always see this player: */
288 for (newp = Monitor; newp < End_monitor; newp++)
289 check(newp, y, x);
291 /* Check if other players can see this player: */
292 for (newp = Player; newp < End_player; newp++) {
293 if (!draw) {
294 /* When un-drawing, show everyone what was under */
295 check(newp, y, x);
296 continue;
298 if (newp == pp) {
299 /* The player can always see themselves: */
300 check(newp, y, x);
301 continue;
303 /* Check if the other player just run out of scans */
304 if (newp->p_scan == 0) {
305 /* The other player is no longer scanning: */
306 newp->p_scan--;
307 showstat(newp);
308 /* Check if the other play is scannning */
309 } else if (newp->p_scan > 0) {
310 /* If this player's not cloacked, draw him: */
311 if (pp->p_cloak < 0)
312 check(newp, y, x);
313 /* And this uses up a scan. */
314 newp->p_scan--;
318 /* Use up one point of cloak time when drawing: */
319 if (draw && pp->p_cloak >= 0) {
320 pp->p_cloak--;
321 /* Check if we ran out of cloak: */
322 if (pp->p_cloak < 0)
323 showstat(pp);
328 * message:
329 * Write a message at the bottom of the screen.
331 void
332 message(PLAYER *pp, const char *s)
334 cgoto(pp, HEIGHT, 0);
335 outstr(pp, s, strlen(s));
336 ce(pp);
340 * translate:
341 * Turn a player character into a more personal player character.
342 * ie: {,},!,i becomes <,>,v,^
344 static char
345 translate(char ch)
347 switch (ch) {
348 case LEFTS:
349 return '<';
350 case RIGHT:
351 return '>';
352 case ABOVE:
353 return '^';
354 case BELOW:
355 return 'v';
357 return ch;
361 * player_sym:
362 * Return the symbol for the player at (y,x) when viewed by player 'pp'.
363 * ie: - unteamed players appear as {,},!,i
364 * - unteamed monitors see all players as team digits
365 * - teamed players see other players on their team, as a digit
367 static int
368 player_sym(PLAYER *pp, int y, int x)
370 PLAYER *npp;
372 npp = play_at(y, x);
373 if (npp->p_ident->i_team == ' ')
374 return Maze[y][x];
375 if (pp->p_ident->i_team == '*')
376 return npp->p_ident->i_team;
377 if (pp->p_ident->i_team != npp->p_ident->i_team)
378 return Maze[y][x];
379 return pp->p_ident->i_team;