xref: /netbsd/games/hunt/huntd/draw.c (revision 6550d01e)
1 /*	$NetBSD: draw.c,v 1.8 2009/08/12 07:42:11 dholland Exp $	*/
2 /*
3  * Copyright (c) 1983-2003, Regents of the University of California.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  * + Redistributions of source code must retain the above copyright
11  *   notice, this list of conditions and the following disclaimer.
12  * + Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  * + Neither the name of the University of California, San Francisco nor
16  *   the names of its contributors may be used to endorse or promote
17  *   products derived from this software without specific prior written
18  *   permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 #ifndef lint
35 __RCSID("$NetBSD: draw.c,v 1.8 2009/08/12 07:42:11 dholland Exp $");
36 #endif /* not lint */
37 
38 #include "hunt.h"
39 
40 static void drawstatus(PLAYER *);
41 static void see(PLAYER *, int);
42 static char translate(char);
43 static int player_sym(PLAYER *, int, int);
44 
45 void
46 drawmaze(PLAYER *pp)
47 {
48 	int x;
49 	char *sp;
50 	int y;
51 	char *endp;
52 
53 	clrscr(pp);
54 	outstr(pp, pp->p_maze[0], WIDTH);
55 	for (y = 1; y < HEIGHT - 1; y++) {
56 		endp = &pp->p_maze[y][WIDTH];
57 		for (x = 0, sp = pp->p_maze[y]; sp < endp; x++, sp++)
58 			if (*sp != SPACE) {
59 				cgoto(pp, y, x);
60 				if (pp->p_x == x && pp->p_y == y)
61 					outch(pp, translate(*sp));
62 				else if (isplayer(*sp))
63 					outch(pp, player_sym(pp, y, x));
64 				else
65 					outch(pp, *sp);
66 			}
67 	}
68 	cgoto(pp, HEIGHT - 1, 0);
69 	outstr(pp, pp->p_maze[HEIGHT - 1], WIDTH);
70 	drawstatus(pp);
71 }
72 
73 /*
74  * drawstatus - put up the status lines (this assumes the screen
75  *		size is 80x24 with the maze being 64x24)
76  */
77 static void
78 drawstatus(PLAYER *pp)
79 {
80 	int i;
81 	PLAYER *np;
82 
83 	cgoto(pp, STAT_AMMO_ROW, STAT_LABEL_COL);
84 	outstr(pp, "Ammo:", 5);
85 	(void) snprintf(Buf, sizeof(Buf), "%3d", pp->p_ammo);
86 	cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
87 	outstr(pp, Buf, 3);
88 
89 	cgoto(pp, STAT_GUN_ROW, STAT_LABEL_COL);
90 	outstr(pp, "Gun:", 4);
91 	cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
92 	outstr(pp, (pp->p_ncshot < MAXNCSHOT) ? " ok" : "   ", 3);
93 
94 	cgoto(pp, STAT_DAM_ROW, STAT_LABEL_COL);
95 	outstr(pp, "Damage:", 7);
96 	(void) snprintf(Buf, sizeof(Buf), "%2d/%2d", pp->p_damage,
97 		pp->p_damcap);
98 	cgoto(pp, STAT_DAM_ROW, STAT_VALUE_COL);
99 	outstr(pp, Buf, 5);
100 
101 	cgoto(pp, STAT_KILL_ROW, STAT_LABEL_COL);
102 	outstr(pp, "Kills:", 6);
103 	(void) snprintf(Buf, sizeof(Buf), "%3d", (pp->p_damcap - MAXDAM) / 2);
104 	cgoto(pp, STAT_KILL_ROW, STAT_VALUE_COL);
105 	outstr(pp, Buf, 3);
106 
107 	cgoto(pp, STAT_PLAY_ROW, STAT_LABEL_COL);
108 	outstr(pp, "Player:", 7);
109 	for (i = STAT_PLAY_ROW + 1, np = Player; np < End_player; np++) {
110 		(void) snprintf(Buf, sizeof(Buf), "%5.2f%c%-10.10s %c",
111 			np->p_ident->i_score,
112 			stat_char(np), np->p_ident->i_name,
113 			np->p_ident->i_team);
114 		cgoto(pp, i++, STAT_NAME_COL);
115 		outstr(pp, Buf, STAT_NAME_LEN);
116 	}
117 
118 #ifdef MONITOR
119 	cgoto(pp, STAT_MON_ROW, STAT_LABEL_COL);
120 	outstr(pp, "Monitor:", 8);
121 	for (i = STAT_MON_ROW + 1, np = Monitor; np < End_monitor; np++) {
122 		(void) snprintf(Buf, sizeof(Buf), "%5.5s %-10.10s %c", " ",
123 			np->p_ident->i_name, np->p_ident->i_team);
124 		cgoto(pp, i++, STAT_NAME_COL);
125 		outstr(pp, Buf, STAT_NAME_LEN);
126 	}
127 #endif
128 }
129 
130 void
131 look(PLAYER *pp)
132 {
133 	int x, y;
134 
135 	x = pp->p_x;
136 	y = pp->p_y;
137 
138 	check(pp, y - 1, x - 1);
139 	check(pp, y - 1, x    );
140 	check(pp, y - 1, x + 1);
141 	check(pp, y    , x - 1);
142 	check(pp, y    , x    );
143 	check(pp, y    , x + 1);
144 	check(pp, y + 1, x - 1);
145 	check(pp, y + 1, x    );
146 	check(pp, y + 1, x + 1);
147 
148 	switch (pp->p_face) {
149 	  case LEFTS:
150 		see(pp, LEFTS);
151 		see(pp, ABOVE);
152 		see(pp, BELOW);
153 		break;
154 	  case RIGHT:
155 		see(pp, RIGHT);
156 		see(pp, ABOVE);
157 		see(pp, BELOW);
158 		break;
159 	  case ABOVE:
160 		see(pp, ABOVE);
161 		see(pp, LEFTS);
162 		see(pp, RIGHT);
163 		break;
164 	  case BELOW:
165 		see(pp, BELOW);
166 		see(pp, LEFTS);
167 		see(pp, RIGHT);
168 		break;
169 #ifdef FLY
170 	  case FLYER:
171 		break;
172 #endif
173 	}
174 	cgoto(pp, y, x);
175 }
176 
177 static void
178 see(PLAYER *pp, int face)
179 {
180 	char *sp;
181 	int y, x, i, cnt;
182 
183 	x = pp->p_x;
184 	y = pp->p_y;
185 
186 	switch (face) {
187 	  case LEFTS:
188 		sp = &Maze[y][x];
189 		for (i = 0; See_over[(int)*--sp]; i++)
190 			continue;
191 
192 		if (i == 0)
193 			break;
194 
195 		cnt = i;
196 		x = pp->p_x - 1;
197 		--y;
198 		while (i--)
199 			check(pp, y, --x);
200 		i = cnt;
201 		x = pp->p_x - 1;
202 		++y;
203 		while (i--)
204 			check(pp, y, --x);
205 		i = cnt;
206 		x = pp->p_x - 1;
207 		++y;
208 		while (i--)
209 			check(pp, y, --x);
210 		break;
211 	  case RIGHT:
212 		sp = &Maze[y][++x];
213 		for (i = 0; See_over[(int)*sp++]; i++)
214 			continue;
215 
216 		if (i == 0)
217 			break;
218 
219 		cnt = i;
220 		x = pp->p_x + 1;
221 		--y;
222 		while (i--)
223 			check(pp, y, ++x);
224 		i = cnt;
225 		x = pp->p_x + 1;
226 		++y;
227 		while (i--)
228 			check(pp, y, ++x);
229 		i = cnt;
230 		x = pp->p_x + 1;
231 		++y;
232 		while (i--)
233 			check(pp, y, ++x);
234 		break;
235 	  case ABOVE:
236 		sp = &Maze[--y][x];
237 		if (!See_over[(int)*sp])
238 			break;
239 		do {
240 			--y;
241 			sp -= sizeof Maze[0];
242 			check(pp, y, x - 1);
243 			check(pp, y, x    );
244 			check(pp, y, x + 1);
245 		} while (See_over[(int)*sp]);
246 		break;
247 	  case BELOW:
248 		sp = &Maze[++y][x];
249 		if (!See_over[(int)*sp])
250 			break;
251 		do {
252 			y++;
253 			sp += sizeof Maze[0];
254 			check(pp, y, x - 1);
255 			check(pp, y, x    );
256 			check(pp, y, x + 1);
257 		} while (See_over[(int)*sp]);
258 		break;
259 	}
260 }
261 
262 void
263 check(PLAYER *pp, int y, int x)
264 {
265 	int indx;
266 	int ch;
267 	PLAYER *rpp;
268 
269 	indx = y * sizeof Maze[0] + x;
270 	ch = ((char *) Maze)[indx];
271 	if (ch != ((char *) pp->p_maze)[indx]) {
272 		rpp = pp;
273 		cgoto(rpp, y, x);
274 		if (x == rpp->p_x && y == rpp->p_y)
275 			outch(rpp, translate(ch));
276 		else if (isplayer(ch))
277 			outch(rpp, player_sym(rpp, y, x));
278 		else
279 			outch(rpp, ch);
280 		((char *) rpp->p_maze)[indx] = ch;
281 	}
282 }
283 
284 /*
285  * showstat
286  *	Update the status of players
287  */
288 void
289 showstat(PLAYER *pp)
290 {
291 	PLAYER *np;
292 	int y;
293 	char c;
294 
295 	y = STAT_PLAY_ROW + 1 + (pp - Player);
296 	c = stat_char(pp);
297 #ifdef MONITOR
298 	for (np = Monitor; np < End_monitor; np++) {
299 		cgoto(np, y, STAT_SCAN_COL);
300 		outch(np, c);
301 	}
302 #endif
303 	for (np = Player; np < End_player; np++) {
304 		cgoto(np, y, STAT_SCAN_COL);
305 		outch(np, c);
306 	}
307 }
308 
309 /*
310  * drawplayer:
311  *	Draw the player on the screen and show him to everyone who's scanning
312  *	unless he is cloaked.
313  */
314 void
315 drawplayer(PLAYER *pp, FLAG draw)
316 {
317 	PLAYER *newp;
318 	int x, y;
319 
320 	x = pp->p_x;
321 	y = pp->p_y;
322 	Maze[y][x] = draw ? pp->p_face : pp->p_over;
323 
324 #ifdef MONITOR
325 	for (newp = Monitor; newp < End_monitor; newp++)
326 		check(newp, y, x);
327 #endif
328 
329 	for (newp = Player; newp < End_player; newp++) {
330 		if (!draw || newp == pp) {
331 			check(newp, y, x);
332 			continue;
333 		}
334 		if (newp->p_scan == 0) {
335 			newp->p_scan--;
336 			showstat(newp);
337 		}
338 		else if (newp->p_scan > 0) {
339 			if (pp->p_cloak < 0)
340 				check(newp, y, x);
341 			newp->p_scan--;
342 		}
343 	}
344 	if (!draw || pp->p_cloak < 0)
345 		return;
346 	if (pp->p_cloak-- == 0)
347 		showstat(pp);
348 }
349 
350 void
351 message(PLAYER *pp, const char *s)
352 {
353 	cgoto(pp, HEIGHT, 0);
354 	outstr(pp, s, strlen(s));
355 	ce(pp);
356 }
357 
358 /*
359  * translate:
360  *	Turn a character into the right direction character if we are
361  *	looking at the current player.
362  */
363 static char
364 translate(char ch)
365 {
366 	switch (ch) {
367 	  case LEFTS:
368 		return '<';
369 	  case RIGHT:
370 		return '>';
371 	  case ABOVE:
372 		return '^';
373 	  case BELOW:
374 		return 'v';
375 	}
376 	return ch;
377 }
378 
379 /*
380  * player_sym:
381  *	Return the player symbol
382  */
383 static int
384 player_sym(PLAYER *pp, int y, int x)
385 {
386 	PLAYER *npp;
387 
388 	npp = play_at(y, x);
389 	if (npp->p_ident->i_team == ' ')
390 		return Maze[y][x];
391 #ifdef MONITOR
392 	if (pp->p_ident->i_team == '*')
393 		return npp->p_ident->i_team;
394 #endif
395 	if (pp->p_ident->i_team != npp->p_ident->i_team)
396 		return Maze[y][x];
397 	return pp->p_ident->i_team;
398 }
399