Home | History | Annotate | Line # | Download | only in huntd
      1 /*	$NetBSD: draw.c,v 1.10 2021/05/02 12:50:45 rillig 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.10 2021/05/02 12:50:45 rillig 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, bool 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