NetBSD/games/hunt/huntd/draw.c

407 lines
8.1 KiB
C

/* $NetBSD: draw.c,v 1.3 2003/06/11 12:00:22 wiz Exp $ */
/*
* Copyright (c) 1983-2003, Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* + Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* + Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* + Neither the name of the University of California, San Francisco nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: draw.c,v 1.3 2003/06/11 12:00:22 wiz Exp $");
#endif /* not lint */
# include "hunt.h"
void
drawmaze(pp)
PLAYER *pp;
{
int x;
char *sp;
int y;
char *endp;
clrscr(pp);
outstr(pp, pp->p_maze[0], WIDTH);
for (y = 1; y < HEIGHT - 1; y++) {
endp = &pp->p_maze[y][WIDTH];
for (x = 0, sp = pp->p_maze[y]; sp < endp; x++, sp++)
if (*sp != SPACE) {
cgoto(pp, y, x);
if (pp->p_x == x && pp->p_y == y)
outch(pp, translate(*sp));
else if (isplayer(*sp))
outch(pp, player_sym(pp, y, x));
else
outch(pp, *sp);
}
}
cgoto(pp, HEIGHT - 1, 0);
outstr(pp, pp->p_maze[HEIGHT - 1], WIDTH);
drawstatus(pp);
}
/*
* drawstatus - put up the status lines (this assumes the screen
* size is 80x24 with the maze being 64x24)
*/
void
drawstatus(pp)
PLAYER *pp;
{
int i;
PLAYER *np;
cgoto(pp, STAT_AMMO_ROW, STAT_LABEL_COL);
outstr(pp, "Ammo:", 5);
(void) sprintf(Buf, "%3d", pp->p_ammo);
cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
outstr(pp, Buf, 3);
cgoto(pp, STAT_GUN_ROW, STAT_LABEL_COL);
outstr(pp, "Gun:", 4);
cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
outstr(pp, (pp->p_ncshot < MAXNCSHOT) ? " ok" : " ", 3);
cgoto(pp, STAT_DAM_ROW, STAT_LABEL_COL);
outstr(pp, "Damage:", 7);
(void) sprintf(Buf, "%2d/%2d", pp->p_damage, pp->p_damcap);
cgoto(pp, STAT_DAM_ROW, STAT_VALUE_COL);
outstr(pp, Buf, 5);
cgoto(pp, STAT_KILL_ROW, STAT_LABEL_COL);
outstr(pp, "Kills:", 6);
(void) sprintf(Buf, "%3d", (pp->p_damcap - MAXDAM) / 2);
cgoto(pp, STAT_KILL_ROW, STAT_VALUE_COL);
outstr(pp, Buf, 3);
cgoto(pp, STAT_PLAY_ROW, STAT_LABEL_COL);
outstr(pp, "Player:", 7);
for (i = STAT_PLAY_ROW + 1, np = Player; np < End_player; np++) {
(void) sprintf(Buf, "%5.2f%c%-10.10s %c", np->p_ident->i_score,
stat_char(np), np->p_ident->i_name,
np->p_ident->i_team);
cgoto(pp, i++, STAT_NAME_COL);
outstr(pp, Buf, STAT_NAME_LEN);
}
# ifdef MONITOR
cgoto(pp, STAT_MON_ROW, STAT_LABEL_COL);
outstr(pp, "Monitor:", 8);
for (i = STAT_MON_ROW + 1, np = Monitor; np < End_monitor; np++) {
(void) sprintf(Buf, "%5.5s %-10.10s %c", " ",
np->p_ident->i_name, np->p_ident->i_team);
cgoto(pp, i++, STAT_NAME_COL);
outstr(pp, Buf, STAT_NAME_LEN);
}
# endif
}
void
look(pp)
PLAYER *pp;
{
int x, y;
x = pp->p_x;
y = pp->p_y;
check(pp, y - 1, x - 1);
check(pp, y - 1, x );
check(pp, y - 1, x + 1);
check(pp, y , x - 1);
check(pp, y , x );
check(pp, y , x + 1);
check(pp, y + 1, x - 1);
check(pp, y + 1, x );
check(pp, y + 1, x + 1);
switch (pp->p_face) {
case LEFTS:
see(pp, LEFTS);
see(pp, ABOVE);
see(pp, BELOW);
break;
case RIGHT:
see(pp, RIGHT);
see(pp, ABOVE);
see(pp, BELOW);
break;
case ABOVE:
see(pp, ABOVE);
see(pp, LEFTS);
see(pp, RIGHT);
break;
case BELOW:
see(pp, BELOW);
see(pp, LEFTS);
see(pp, RIGHT);
break;
# ifdef FLY
case FLYER:
break;
# endif
}
cgoto(pp, y, x);
}
void
see(pp, face)
PLAYER *pp;
int face;
{
char *sp;
int y, x, i, cnt;
x = pp->p_x;
y = pp->p_y;
switch (face) {
case LEFTS:
sp = &Maze[y][x];
for (i = 0; See_over[(int)*--sp]; i++)
continue;
if (i == 0)
break;
cnt = i;
x = pp->p_x - 1;
--y;
while (i--)
check(pp, y, --x);
i = cnt;
x = pp->p_x - 1;
++y;
while (i--)
check(pp, y, --x);
i = cnt;
x = pp->p_x - 1;
++y;
while (i--)
check(pp, y, --x);
break;
case RIGHT:
sp = &Maze[y][++x];
for (i = 0; See_over[(int)*sp++]; i++)
continue;
if (i == 0)
break;
cnt = i;
x = pp->p_x + 1;
--y;
while (i--)
check(pp, y, ++x);
i = cnt;
x = pp->p_x + 1;
++y;
while (i--)
check(pp, y, ++x);
i = cnt;
x = pp->p_x + 1;
++y;
while (i--)
check(pp, y, ++x);
break;
case ABOVE:
sp = &Maze[--y][x];
if (!See_over[(int)*sp])
break;
do {
--y;
sp -= sizeof Maze[0];
check(pp, y, x - 1);
check(pp, y, x );
check(pp, y, x + 1);
} while (See_over[(int)*sp]);
break;
case BELOW:
sp = &Maze[++y][x];
if (!See_over[(int)*sp])
break;
do {
y++;
sp += sizeof Maze[0];
check(pp, y, x - 1);
check(pp, y, x );
check(pp, y, x + 1);
} while (See_over[(int)*sp]);
break;
}
}
void
check(pp, y, x)
PLAYER *pp;
int y, x;
{
int index;
int ch;
PLAYER *rpp;
index = y * sizeof Maze[0] + x;
ch = ((char *) Maze)[index];
if (ch != ((char *) pp->p_maze)[index]) {
rpp = pp;
cgoto(rpp, y, x);
if (x == rpp->p_x && y == rpp->p_y)
outch(rpp, translate(ch));
else if (isplayer(ch))
outch(rpp, player_sym(rpp, y, x));
else
outch(rpp, ch);
((char *) rpp->p_maze)[index] = ch;
}
}
/*
* showstat
* Update the status of players
*/
void
showstat(pp)
PLAYER *pp;
{
PLAYER *np;
int y;
char c;
y = STAT_PLAY_ROW + 1 + (pp - Player);
c = stat_char(pp);
# ifdef MONITOR
for (np = Monitor; np < End_monitor; np++) {
cgoto(np, y, STAT_SCAN_COL);
outch(np, c);
}
# endif
for (np = Player; np < End_player; np++) {
cgoto(np, y, STAT_SCAN_COL);
outch(np, c);
}
}
/*
* drawplayer:
* Draw the player on the screen and show him to everyone who's scanning
* unless he is cloaked.
*/
void
drawplayer(pp, draw)
PLAYER *pp;
FLAG draw;
{
PLAYER *newp;
int x, y;
x = pp->p_x;
y = pp->p_y;
Maze[y][x] = draw ? pp->p_face : pp->p_over;
# ifdef MONITOR
for (newp = Monitor; newp < End_monitor; newp++)
check(newp, y, x);
# endif
for (newp = Player; newp < End_player; newp++) {
if (!draw || newp == pp) {
check(newp, y, x);
continue;
}
if (newp->p_scan == 0) {
newp->p_scan--;
showstat(newp);
}
else if (newp->p_scan > 0) {
if (pp->p_cloak < 0)
check(newp, y, x);
newp->p_scan--;
}
}
if (!draw || pp->p_cloak < 0)
return;
if (pp->p_cloak-- == 0)
showstat(pp);
}
void
message(pp, s)
PLAYER *pp;
char *s;
{
cgoto(pp, HEIGHT, 0);
outstr(pp, s, strlen(s));
ce(pp);
}
/*
* translate:
* Turn a character into the right direction character if we are
* looking at the current player.
*/
char
translate(ch)
char ch;
{
switch (ch) {
case LEFTS:
return '<';
case RIGHT:
return '>';
case ABOVE:
return '^';
case BELOW:
return 'v';
}
return ch;
}
/*
* player_sym:
* Return the player symbol
*/
int
player_sym(pp, y, x)
PLAYER *pp;
int y, x;
{
PLAYER *npp;
npp = play_at(y, x);
if (npp->p_ident->i_team == ' ')
return Maze[y][x];
#ifdef MONITOR
if (pp->p_ident->i_team == '*')
return npp->p_ident->i_team;
#endif
if (pp->p_ident->i_team != npp->p_ident->i_team)
return Maze[y][x];
return pp->p_ident->i_team;
}