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