186d7f5d3SJohn Marino /*-
286d7f5d3SJohn Marino * Copyright (c) 1983-2003, Regents of the University of California.
386d7f5d3SJohn Marino * All rights reserved.
486d7f5d3SJohn Marino *
586d7f5d3SJohn Marino * Redistribution and use in source and binary forms, with or without
686d7f5d3SJohn Marino * modification, are permitted provided that the following conditions are
786d7f5d3SJohn Marino * met:
886d7f5d3SJohn Marino *
986d7f5d3SJohn Marino * 1. Redistributions of source code must retain the above copyright
1086d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer.
1186d7f5d3SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
1286d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer in the
1386d7f5d3SJohn Marino * documentation and/or other materials provided with the distribution.
1486d7f5d3SJohn Marino * 3. Neither the name of the University of California, San Francisco nor
1586d7f5d3SJohn Marino * the names of its contributors may be used to endorse or promote
1686d7f5d3SJohn Marino * products derived from this software without specific prior written
1786d7f5d3SJohn Marino * permission.
1886d7f5d3SJohn Marino *
1986d7f5d3SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
2086d7f5d3SJohn Marino * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2186d7f5d3SJohn Marino * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
2286d7f5d3SJohn Marino * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2386d7f5d3SJohn Marino * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2486d7f5d3SJohn Marino * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2586d7f5d3SJohn Marino * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2686d7f5d3SJohn Marino * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2786d7f5d3SJohn Marino * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2886d7f5d3SJohn Marino * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2986d7f5d3SJohn Marino * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3086d7f5d3SJohn Marino *
3186d7f5d3SJohn Marino * $OpenBSD: expl.c,v 1.9 2007/09/04 22:39:31 hshoexer Exp $
3286d7f5d3SJohn Marino * $NetBSD: expl.c,v 1.2 1997/10/10 16:33:18 lukem Exp $
3386d7f5d3SJohn Marino * $DragonFly: src/games/hunt/huntd/expl.c,v 1.2 2008/09/04 16:12:51 swildner Exp $
3486d7f5d3SJohn Marino */
3586d7f5d3SJohn Marino
3686d7f5d3SJohn Marino #include <stdlib.h>
3786d7f5d3SJohn Marino #include <syslog.h>
3886d7f5d3SJohn Marino #include <string.h>
3986d7f5d3SJohn Marino #include "hunt.h"
4086d7f5d3SJohn Marino #include "server.h"
4186d7f5d3SJohn Marino #include "conf.h"
4286d7f5d3SJohn Marino
4386d7f5d3SJohn Marino static void remove_wall(int, int);
4486d7f5d3SJohn Marino static void init_removed(void);
4586d7f5d3SJohn Marino
4686d7f5d3SJohn Marino
4786d7f5d3SJohn Marino /*
4886d7f5d3SJohn Marino * showexpl:
4986d7f5d3SJohn Marino * Show the explosions as they currently are
5086d7f5d3SJohn Marino */
5186d7f5d3SJohn Marino void
showexpl(int y,int x,char type)5286d7f5d3SJohn Marino showexpl(int y, int x, char type)
5386d7f5d3SJohn Marino {
5486d7f5d3SJohn Marino PLAYER *pp;
5586d7f5d3SJohn Marino EXPL *ep;
5686d7f5d3SJohn Marino
5786d7f5d3SJohn Marino if (y < 0 || y >= HEIGHT)
5886d7f5d3SJohn Marino return;
5986d7f5d3SJohn Marino if (x < 0 || x >= WIDTH)
6086d7f5d3SJohn Marino return;
6186d7f5d3SJohn Marino ep = (EXPL *) malloc(sizeof (EXPL)); /* NOSTRICT */
6286d7f5d3SJohn Marino if (ep == NULL) {
6386d7f5d3SJohn Marino logit(LOG_ERR, "malloc");
6486d7f5d3SJohn Marino return;
6586d7f5d3SJohn Marino }
6686d7f5d3SJohn Marino ep->e_y = y;
6786d7f5d3SJohn Marino ep->e_x = x;
6886d7f5d3SJohn Marino ep->e_char = type;
6986d7f5d3SJohn Marino ep->e_next = NULL;
7086d7f5d3SJohn Marino if (Last_expl == NULL)
7186d7f5d3SJohn Marino Expl[0] = ep;
7286d7f5d3SJohn Marino else
7386d7f5d3SJohn Marino Last_expl->e_next = ep;
7486d7f5d3SJohn Marino Last_expl = ep;
7586d7f5d3SJohn Marino for (pp = Player; pp < End_player; pp++) {
7686d7f5d3SJohn Marino if (pp->p_maze[y][x] == type)
7786d7f5d3SJohn Marino continue;
7886d7f5d3SJohn Marino pp->p_maze[y][x] = type;
7986d7f5d3SJohn Marino cgoto(pp, y, x);
8086d7f5d3SJohn Marino outch(pp, type);
8186d7f5d3SJohn Marino }
8286d7f5d3SJohn Marino for (pp = Monitor; pp < End_monitor; pp++) {
8386d7f5d3SJohn Marino if (pp->p_maze[y][x] == type)
8486d7f5d3SJohn Marino continue;
8586d7f5d3SJohn Marino pp->p_maze[y][x] = type;
8686d7f5d3SJohn Marino cgoto(pp, y, x);
8786d7f5d3SJohn Marino outch(pp, type);
8886d7f5d3SJohn Marino }
8986d7f5d3SJohn Marino switch (Maze[y][x]) {
9086d7f5d3SJohn Marino case WALL1:
9186d7f5d3SJohn Marino case WALL2:
9286d7f5d3SJohn Marino case WALL3:
9386d7f5d3SJohn Marino case DOOR:
9486d7f5d3SJohn Marino case WALL4:
9586d7f5d3SJohn Marino case WALL5:
9686d7f5d3SJohn Marino if (y >= UBOUND && y < DBOUND && x >= LBOUND && x < RBOUND)
9786d7f5d3SJohn Marino remove_wall(y, x);
9886d7f5d3SJohn Marino break;
9986d7f5d3SJohn Marino }
10086d7f5d3SJohn Marino }
10186d7f5d3SJohn Marino
10286d7f5d3SJohn Marino /*
10386d7f5d3SJohn Marino * rollexpl:
10486d7f5d3SJohn Marino * Roll the explosions over, so the next one in the list is at the
10586d7f5d3SJohn Marino * top
10686d7f5d3SJohn Marino */
10786d7f5d3SJohn Marino void
rollexpl(void)10886d7f5d3SJohn Marino rollexpl(void)
10986d7f5d3SJohn Marino {
11086d7f5d3SJohn Marino EXPL *ep;
11186d7f5d3SJohn Marino PLAYER *pp;
11286d7f5d3SJohn Marino int y, x;
11386d7f5d3SJohn Marino char c;
11486d7f5d3SJohn Marino EXPL *nextep;
11586d7f5d3SJohn Marino
11686d7f5d3SJohn Marino for (ep = Expl[EXPLEN - 1]; ep != NULL; ep = nextep) {
11786d7f5d3SJohn Marino nextep = ep->e_next;
11886d7f5d3SJohn Marino y = ep->e_y;
11986d7f5d3SJohn Marino x = ep->e_x;
12086d7f5d3SJohn Marino if (y < UBOUND || y >= DBOUND || x < LBOUND || x >= RBOUND)
12186d7f5d3SJohn Marino c = Maze[y][x];
12286d7f5d3SJohn Marino else
12386d7f5d3SJohn Marino c = SPACE;
12486d7f5d3SJohn Marino for (pp = Player; pp < End_player; pp++)
12586d7f5d3SJohn Marino if (pp->p_maze[y][x] == ep->e_char) {
12686d7f5d3SJohn Marino pp->p_maze[y][x] = c;
12786d7f5d3SJohn Marino cgoto(pp, y, x);
12886d7f5d3SJohn Marino outch(pp, c);
12986d7f5d3SJohn Marino }
13086d7f5d3SJohn Marino for (pp = Monitor; pp < End_monitor; pp++)
13186d7f5d3SJohn Marino check(pp, y, x);
13286d7f5d3SJohn Marino free((char *) ep);
13386d7f5d3SJohn Marino }
13486d7f5d3SJohn Marino memmove(&Expl[1], &Expl[0], (EXPLEN - 1) * sizeof Expl[0]);
13586d7f5d3SJohn Marino /* for (x = EXPLEN - 1; x > 0; x--)
13686d7f5d3SJohn Marino Expl[x] = Expl[x - 1]; */
13786d7f5d3SJohn Marino Last_expl = Expl[0] = NULL;
13886d7f5d3SJohn Marino }
13986d7f5d3SJohn Marino
14086d7f5d3SJohn Marino int
can_rollexpl(void)14186d7f5d3SJohn Marino can_rollexpl(void)
14286d7f5d3SJohn Marino {
14386d7f5d3SJohn Marino int i;
14486d7f5d3SJohn Marino
14586d7f5d3SJohn Marino for (i = EXPLEN - 1; i >= 0; i--)
14686d7f5d3SJohn Marino if (Expl[i] != NULL)
14786d7f5d3SJohn Marino return 1;
14886d7f5d3SJohn Marino return 0;
14986d7f5d3SJohn Marino }
15086d7f5d3SJohn Marino
15186d7f5d3SJohn Marino static REGEN *removed = NULL;
15286d7f5d3SJohn Marino static REGEN *rem_index = NULL;
15386d7f5d3SJohn Marino
15486d7f5d3SJohn Marino static void
init_removed(void)15586d7f5d3SJohn Marino init_removed(void)
15686d7f5d3SJohn Marino {
15786d7f5d3SJohn Marino rem_index = removed = calloc(conf_maxremove, sizeof(REGEN));
15886d7f5d3SJohn Marino if (rem_index == NULL) {
15986d7f5d3SJohn Marino logit(LOG_ERR, "malloc");
16086d7f5d3SJohn Marino cleanup(1);
16186d7f5d3SJohn Marino }
16286d7f5d3SJohn Marino }
16386d7f5d3SJohn Marino
16486d7f5d3SJohn Marino /*
16586d7f5d3SJohn Marino * remove_wall - add a location where the wall was blown away.
16686d7f5d3SJohn Marino * if there is no space left over, put the a wall at
16786d7f5d3SJohn Marino * the location currently pointed at.
16886d7f5d3SJohn Marino */
16986d7f5d3SJohn Marino static void
remove_wall(int y,int x)17086d7f5d3SJohn Marino remove_wall(int y, int x)
17186d7f5d3SJohn Marino {
17286d7f5d3SJohn Marino REGEN *r;
17386d7f5d3SJohn Marino PLAYER *pp;
17486d7f5d3SJohn Marino char save_char = 0;
17586d7f5d3SJohn Marino
17686d7f5d3SJohn Marino if (removed == NULL)
17786d7f5d3SJohn Marino clearwalls();
17886d7f5d3SJohn Marino
17986d7f5d3SJohn Marino r = rem_index;
18086d7f5d3SJohn Marino while (r->r_y != 0) {
18186d7f5d3SJohn Marino switch (Maze[r->r_y][r->r_x]) {
18286d7f5d3SJohn Marino case SPACE:
18386d7f5d3SJohn Marino case LEFTS:
18486d7f5d3SJohn Marino case RIGHT:
18586d7f5d3SJohn Marino case ABOVE:
18686d7f5d3SJohn Marino case BELOW:
18786d7f5d3SJohn Marino case FLYER:
18886d7f5d3SJohn Marino save_char = Maze[r->r_y][r->r_x];
18986d7f5d3SJohn Marino goto found;
19086d7f5d3SJohn Marino }
19186d7f5d3SJohn Marino if (++r >= removed + conf_maxremove)
19286d7f5d3SJohn Marino r = removed;
19386d7f5d3SJohn Marino }
19486d7f5d3SJohn Marino
19586d7f5d3SJohn Marino found:
19686d7f5d3SJohn Marino if (r->r_y != 0) {
19786d7f5d3SJohn Marino /* Slot being used, put back this wall */
19886d7f5d3SJohn Marino if (save_char == SPACE)
19986d7f5d3SJohn Marino Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x];
20086d7f5d3SJohn Marino else {
20186d7f5d3SJohn Marino /* We throw the player off the wall: */
20286d7f5d3SJohn Marino pp = play_at(r->r_y, r->r_x);
20386d7f5d3SJohn Marino if (pp->p_flying >= 0)
20486d7f5d3SJohn Marino pp->p_flying += rand_num(conf_flytime / 2);
20586d7f5d3SJohn Marino else {
20686d7f5d3SJohn Marino pp->p_flying = rand_num(conf_flytime);
20786d7f5d3SJohn Marino pp->p_flyx = 2 * rand_num(conf_flystep + 1) -
20886d7f5d3SJohn Marino conf_flystep;
20986d7f5d3SJohn Marino pp->p_flyy = 2 * rand_num(conf_flystep + 1) -
21086d7f5d3SJohn Marino conf_flystep;
21186d7f5d3SJohn Marino }
21286d7f5d3SJohn Marino pp->p_over = Orig_maze[r->r_y][r->r_x];
21386d7f5d3SJohn Marino pp->p_face = FLYER;
21486d7f5d3SJohn Marino Maze[r->r_y][r->r_x] = FLYER;
21586d7f5d3SJohn Marino showexpl(r->r_y, r->r_x, FLYER);
21686d7f5d3SJohn Marino }
21786d7f5d3SJohn Marino Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x];
21886d7f5d3SJohn Marino if (conf_random && rand_num(100) < conf_prandom)
21986d7f5d3SJohn Marino Maze[r->r_y][r->r_x] = DOOR;
22086d7f5d3SJohn Marino if (conf_reflect && rand_num(100) == conf_preflect)
22186d7f5d3SJohn Marino Maze[r->r_y][r->r_x] = WALL4;
22286d7f5d3SJohn Marino for (pp = Monitor; pp < End_monitor; pp++)
22386d7f5d3SJohn Marino check(pp, r->r_y, r->r_x);
22486d7f5d3SJohn Marino }
22586d7f5d3SJohn Marino
22686d7f5d3SJohn Marino r->r_y = y;
22786d7f5d3SJohn Marino r->r_x = x;
22886d7f5d3SJohn Marino if (++r >= removed + conf_maxremove)
22986d7f5d3SJohn Marino rem_index = removed;
23086d7f5d3SJohn Marino else
23186d7f5d3SJohn Marino rem_index = r;
23286d7f5d3SJohn Marino
23386d7f5d3SJohn Marino Maze[y][x] = SPACE;
23486d7f5d3SJohn Marino for (pp = Monitor; pp < End_monitor; pp++)
23586d7f5d3SJohn Marino check(pp, y, x);
23686d7f5d3SJohn Marino }
23786d7f5d3SJohn Marino
23886d7f5d3SJohn Marino /*
23986d7f5d3SJohn Marino * clearwalls:
24086d7f5d3SJohn Marino * Clear out the walls array
24186d7f5d3SJohn Marino */
24286d7f5d3SJohn Marino void
clearwalls(void)24386d7f5d3SJohn Marino clearwalls(void)
24486d7f5d3SJohn Marino {
24586d7f5d3SJohn Marino REGEN *rp;
24686d7f5d3SJohn Marino
24786d7f5d3SJohn Marino if (removed == NULL)
24886d7f5d3SJohn Marino init_removed();
24986d7f5d3SJohn Marino for (rp = removed; rp < removed + conf_maxremove; rp++)
25086d7f5d3SJohn Marino rp->r_y = 0;
25186d7f5d3SJohn Marino rem_index = removed;
25286d7f5d3SJohn Marino }
253