Ejemplo n.º 1
0
/**
 * Initialize the terminal of a player.
 * @param[in] pp A player.
 * [PSR]
 */
void stmonitor(PLAYER *pp) {
	int line;
	PLAYER *npp;

	memcpy(pp->p_maze, maze, sizeof maze);

	drawmaze(pp);

	(void) sprintf(gen_buf, "%5.5s%c%-10.10s %c", " ", stat_char(pp),
			pp->p_ident->i_name, pp->p_ident->i_team);
	line = STAT_MON_ROW + 1 + (pp - monitor);
	for (npp = player; npp < end_player; npp++) {
		cgoto(npp, line, STAT_NAME_COL);
		outstr(npp, gen_buf, STAT_NAME_LEN);
	}
	for (npp = monitor; npp < end_monitor; npp++) {
		cgoto(npp, line, STAT_NAME_COL);
		outstr(npp, gen_buf, STAT_NAME_LEN);
	}

	sendcom(pp, REFRESH);
	sendcom(pp, READY, 0);
	(void) fflush(pp->p_output);
}
Ejemplo n.º 2
0
/*
 * fire_slime:
 *	Fire a slime shot in the given direction
 */
static void
fire_slime(PLAYER *pp, int req_index)
{
	if (pp == NULL)
		return;

	/* Check configuration: */
	if (!conf_ooze)
		return;

	/* Drop the slime type back util we can afford it: */
	while (req_index >= 0 && pp->p_ammo < slime_req[req_index])
		req_index--;

	/* Can we afford to slime at all? */
	if (req_index < 0) {
		message(pp, "Not enough charges.");
		return;
	}

	/* Is the gun too hot? */
	if (pp->p_ncshot > conf_maxncshot)
		return;

	/* Heat up the gun: */
	if (pp->p_ncshot++ == conf_maxncshot) {
		/* The gun has overheated: */
		outyx(pp, STAT_GUN_ROW, STAT_VALUE_COL, "   ");
	}

	/* Use up some ammo: */
	pp->p_ammo -= slime_req[req_index];
	ammo_update(pp);

	/* Start the slime moving: */
	add_shot(SLIME, pp->p_y, pp->p_x, pp->p_face,
		slime_req[req_index] * conf_slimefactor, pp, FALSE, pp->p_face);
	pp->p_undershot = TRUE;

	/* Show the object to everyone: */
	showexpl(pp->p_y, pp->p_x, SLIME);
	sendcom(ALL_PLAYERS, REFRESH);
}
Ejemplo n.º 3
0
/*
 * mon_execute:
 *	Execute a single monitor command
 */
void
mon_execute(PLAYER *pp)
{
	char	ch;

	ch = pp->p_cbuf[pp->p_ncount++];

	switch (ch) {
	  case CTRL('L'):
		/* Redraw messed-up screen */
		sendcom(pp, REDRAW);
		break;
	  case 'q':
		/* Quit client */
		(void) strlcpy(pp->p_death, "| Quit |", sizeof pp->p_death);
		break;
	  default:
		/* Ignore everything else */
		;
	}
}
Ejemplo n.º 4
0
/*
 * fire:
 *	Fire a shot of the given type in the given direction
 */
static void
fire(PLAYER *pp, int req_index)
{
	if (pp == NULL)
		return;

	/* Drop the shot type down until we can afford it: */
	while (req_index >= 0 && pp->p_ammo < shot_req[req_index])
		req_index--;

	/* Can we shoot at all? */
	if (req_index < 0) {
		message(pp, "Not enough charges.");
		return;
	}

	/* Check if the gun is too hot: */
	if (pp->p_ncshot > conf_maxncshot)
		return;

	/* Heat up the gun: */
	if (pp->p_ncshot++ == conf_maxncshot) {
		/* The gun has overheated: */
		outyx(pp, STAT_GUN_ROW, STAT_VALUE_COL, "   ");
	}

	/* Use up some ammo: */
	pp->p_ammo -= shot_req[req_index];
	ammo_update(pp);

	/* Start the bullet moving: */
	add_shot(shot_type[req_index], pp->p_y, pp->p_x, pp->p_face,
		shot_req[req_index], pp, FALSE, pp->p_face);
	pp->p_undershot = TRUE;

	/* Show the bullet to everyone: */
	showexpl(pp->p_y, pp->p_x, shot_type[req_index]);
	sendcom(ALL_PLAYERS, REFRESH);
}
Ejemplo n.º 5
0
/*
 * cleanup:
 *	Exit with the given value, cleaning up any droppings lying around
 */
void
cleanup(int eval)
{
	PLAYER	*pp;

	/* Place their cursor in a friendly position: */
	cgoto(ALL_PLAYERS, HEIGHT, 0);

	/* Send them all the ENDWIN command: */
	sendcom(ALL_PLAYERS, ENDWIN, LAST_PLAYER);

	/* And close their connections: */
	for (pp = Player; pp < End_player; pp++)
		(void) fclose(pp->p_output);
	for (pp = Monitor; pp < End_monitor; pp++)
		(void) fclose(pp->p_output);

	/* Close the server socket: */
	(void) close(Socket);

	/* The end: */
	logx(LOG_INFO, "game over");
	exit(eval);
}
Ejemplo n.º 6
0
/*
 * move_player:
 *	Execute a move in the given direction
 */
static void
move_player(PLAYER *pp, int dir)
{
	PLAYER *newp;
	int x, y;
	bool moved;
	BULLET *bp;

	y = pp->p_y;
	x = pp->p_x;

	switch (dir) {
	  case LEFTS:
		x--;
		break;
	  case RIGHT:
		x++;
		break;
	  case ABOVE:
		y--;
		break;
	  case BELOW:
		y++;
		break;
	}

	moved = false;
	switch (Maze[y][x]) {
	  case SPACE:
#ifdef RANDOM
	  case DOOR:
#endif
		moved = true;
		break;
	  case WALL1:
	  case WALL2:
	  case WALL3:
#ifdef REFLECT
	  case WALL4:
	  case WALL5:
#endif
		break;
	  case MINE:
	  case GMINE:
		if (dir == pp->p_face)
			pickup(pp, y, x, 2, Maze[y][x]);
		else if (opposite(dir, pp->p_face))
			pickup(pp, y, x, 95, Maze[y][x]);
		else
			pickup(pp, y, x, 50, Maze[y][x]);
		Maze[y][x] = SPACE;
		moved = true;
		break;
	  case SHOT:
	  case GRENADE:
	  case SATCHEL:
	  case BOMB:
#ifdef OOZE
	  case SLIME:
#endif
#ifdef DRONE
	  case DSHOT:
#endif
		bp = is_bullet(y, x);
		if (bp != NULL)
			bp->b_expl = true;
		Maze[y][x] = SPACE;
		moved = true;
		break;
	  case LEFTS:
	  case RIGHT:
	  case ABOVE:
	  case BELOW:
		if (dir != pp->p_face)
			sendcom(pp, BELL);
		else {
			newp = play_at(y, x);
			checkdam(newp, pp, pp->p_ident, STABDAM, KNIFE);
		}
		break;
#ifdef FLY
	  case FLYER:
		newp = play_at(y, x);
		message(newp, "Oooh, there's a short guy waving at you!");
		message(pp, "You couldn't quite reach him!");
		break;
#endif
#ifdef BOOTS
	  case BOOT:
	  case BOOT_PAIR:
		if (Maze[y][x] == BOOT)
			pp->p_nboots++;
		else
			pp->p_nboots += 2;
		for (newp = Boot; newp < &Boot[NBOOTS]; newp++) {
			if (newp->p_flying < 0)
				continue;
			if (newp->p_y == y && newp->p_x == x) {
				newp->p_flying = -1;
				if (newp->p_undershot)
					fixshots(y, x, newp->p_over);
			}
		}
		if (pp->p_nboots == 2)
			message(pp, "Wow!  A pair of boots!");
		else
			message(pp, "You can hobble around on one boot.");
		Maze[y][x] = SPACE;
		moved = true;
		break;
#endif
	}
	if (moved) {
		if (pp->p_ncshot > 0)
			if (--pp->p_ncshot == MAXNCSHOT) {
				cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
				outstr(pp, " ok", 3);
			}
		if (pp->p_undershot) {
			fixshots(pp->p_y, pp->p_x, pp->p_over);
			pp->p_undershot = false;
		}
		drawplayer(pp, false);
		pp->p_over = Maze[y][x];
		pp->p_y = y;
		pp->p_x = x;
		drawplayer(pp, true);
	}
}
Ejemplo n.º 7
0
/*
 * main:
 *	The main program.
 */
int
main(int ac, char **av)
{
	PLAYER		*pp;
	int		had_char;
	static fd_set	read_fds;
	static FLAG	first = TRUE;
	static FLAG	server = FALSE;
	int		c;
	static struct timeval	linger = { 0, 0 };
	static struct timeval	timeout = { 0, 0 }, *to;
	struct spawn	*sp, *spnext;
	int		ret;
	int		nready;
	int		fd;

	First_arg = av[0];

	config();

	while ((c = getopt(ac, av, "sp:a:D:")) != -1) {
		switch (c) {
		  case 's':
			server = TRUE;
			break;
		  case 'p':
			should_announce = FALSE;
			Server_port = atoi(optarg);
			break;
		  case 'a':
			if (!inet_aton(optarg, (struct in_addr *)&Server_addr))
				err(1, "bad interface address: %s", optarg);
			break;
		  case 'D':
			config_arg(optarg);
			break;
		  default:
erred:
			fprintf(stderr,
			    "usage: %s [-s] [-a addr] [-Dvar=value ...] "
			    "[-p port]\n",
			    av[0]);
			exit(2);
		}
	}
	if (optind < ac)
		goto erred;

	/* Open syslog: */
	openlog("huntd", LOG_PID | (conf_logerr && !server? LOG_PERROR : 0),
		LOG_DAEMON);

	/* Initialise game parameters: */
	init();

again:
	do {
		/* First, poll to see if we can get input */
		do {
			read_fds = Fds_mask;
			errno = 0;
			timerclear(&timeout);
			nready = select(Num_fds, &read_fds, NULL, NULL,
			    &timeout);
			if (nready < 0 && errno != EINTR) {
				logit(LOG_ERR, "select");
				cleanup(1);
			}
		} while (nready < 0);

		if (nready == 0) {
			/*
			 * Nothing was ready. We do some work now
			 * to see if the simulation has any pending work
			 * to do, and decide if we need to block
			 * indefinitely or just timeout.
			 */
			do {
				if (conf_simstep && can_moveshots()) {
				/*
				 * block for a short time before continuing
				 * with explosions, bullets and whatnot
				 */
					to = &timeout;
					to->tv_sec =  conf_simstep / 1000000;
					to->tv_usec = conf_simstep % 1000000;
				} else
				/*
				 * since there's nothing going on,
				 * just block waiting for external activity
				 */
					to = NULL;

				read_fds = Fds_mask;
				errno = 0;
				nready = select(Num_fds, &read_fds, NULL, NULL,
				    to);
				if (nready < 0 && errno != EINTR) {
					logit(LOG_ERR, "select");
					cleanup(1);
				}
			} while (nready < 0);
		}

		/* Remember which descriptors are active: */
		Have_inp = read_fds;

		/* Answer new player connections: */
		if (FD_ISSET(Socket, &Have_inp))
			answer_first();

		/* Continue answering new player connections: */
		for (sp = Spawn; sp; ) {
			spnext = sp->next;
			fd = sp->fd;
			if (FD_ISSET(fd, &Have_inp) && answer_next(sp)) {
				/*
				 * Remove from the spawn list. (fd remains in
				 * read set).
				 */
				*sp->prevnext = sp->next;
				if (sp->next)
					sp->next->prevnext = sp->prevnext;
				free(sp);

				/* We probably consumed all data. */
				FD_CLR(fd, &Have_inp);

				/* Announce game if this is the first spawn. */
				if (first && should_announce)
					announce_game();
				first = FALSE;
			}
			sp = spnext;
		}

		/* Process input and move bullets until we've exhausted input */
		had_char = TRUE;
		while (had_char) {

			moveshots();
			for (pp = Player; pp < End_player; )
				if (pp->p_death[0] != '\0')
					zap(pp, TRUE);
				else
					pp++;
			for (pp = Monitor; pp < End_monitor; )
				if (pp->p_death[0] != '\0')
					zap(pp, FALSE);
				else
					pp++;

			had_char = FALSE;
			for (pp = Player; pp < End_player; pp++)
				if (havechar(pp)) {
					execute(pp);
					pp->p_nexec++;
					had_char = TRUE;
				}
			for (pp = Monitor; pp < End_monitor; pp++)
				if (havechar(pp)) {
					mon_execute(pp);
					pp->p_nexec++;
					had_char = TRUE;
				}
		}

		/* Handle a datagram sent to the server socket: */
		if (FD_ISSET(Server_socket, &Have_inp))
			handle_wkport(Server_socket);

		/* Answer statistics connections: */
		if (FD_ISSET(Status, &Have_inp))
			send_stats();

		/* Flush/synchronize all the displays: */
		for (pp = Player; pp < End_player; pp++) {
			if (FD_ISSET(pp->p_fd, &read_fds)) {
				sendcom(pp, READY, pp->p_nexec);
				pp->p_nexec = 0;
			}
			flush(pp);
		}
		for (pp = Monitor; pp < End_monitor; pp++) {
			if (FD_ISSET(pp->p_fd, &read_fds)) {
				sendcom(pp, READY, pp->p_nexec);
				pp->p_nexec = 0;
			}
			flush(pp);
		}
	} while (Nplayer > 0);

	/* No more players! */

	/* No players yet or a continuous game? */
	if (first || conf_linger < 0)
		goto again;

	/* Wait a short while for one to come back: */
	read_fds = Fds_mask;
	linger.tv_sec = conf_linger;
	while ((ret = select(Num_fds, &read_fds, NULL, NULL, &linger)) < 0) {
		if (errno != EINTR) {
			logit(LOG_WARNING, "select");
			break;
		}
		read_fds = Fds_mask;
		linger.tv_sec = conf_linger;
		linger.tv_usec = 0;
	}
	if (ret > 0)
		/* Someone returned! Resume the game: */
		goto again;
	/* else, it timed out, and the game is really over. */

	/* If we are an inetd server, we should re-init the map and restart: */
	if (server) {
		clear_scores();
		makemaze();
		clearwalls();
		makeboots();
		first = TRUE;
		goto again;
	}

	/* Get rid of any attached monitors: */
	for (pp = Monitor; pp < End_monitor; )
		zap(pp, FALSE);

	/* Fin: */
	cleanup(0);
	exit(0);
}
Ejemplo n.º 8
0
/*
 * zap:
 *	Kill off a player and take them out of the game.
 *	The 'was_player' flag indicates that the player was not
 *	a monitor and needs extra cleaning up.
 */
static void
zap(PLAYER *pp, FLAG was_player)
{
	int	len;
	BULLET	*bp;
	PLAYER	*np;
	int	x, y;
	int	savefd;

	if (was_player) {
		/* If they died from a shot, clean up shrapnel */
		if (pp->p_undershot)
			fixshots(pp->p_y, pp->p_x, pp->p_over);
		/* Let the player see their last position: */
		drawplayer(pp, FALSE);
		/* Remove from game: */
		Nplayer--;
	}

	/* Display the cause of death in the centre of the screen: */
	len = strlen(pp->p_death);
	x = (WIDTH - len) / 2;
	outyx(pp, HEIGHT / 2, x, "%s", pp->p_death);

	/* Put some horizontal lines around and below the death message: */
	memset(pp->p_death + 1, '-', len - 2);
	pp->p_death[0] = '+';
	pp->p_death[len - 1] = '+';
	outyx(pp, HEIGHT / 2 - 1, x, "%s", pp->p_death);
	outyx(pp, HEIGHT / 2 + 1, x, "%s", pp->p_death);

	/* Move to bottom left */
	cgoto(pp, HEIGHT, 0);

	savefd = pp->p_fd;

	if (was_player) {
		int	expl_charge;
		int	expl_type;
		int	ammo_exploding;

		/* Check all the bullets: */
		for (bp = Bullets; bp != NULL; bp = bp->b_next) {
			if (bp->b_owner == pp)
				/* Zapped players can't own bullets: */
				bp->b_owner = NULL;
			if (bp->b_x == pp->p_x && bp->b_y == pp->p_y)
				/* Bullets over the player are now over air: */
				bp->b_over = SPACE;
		}

		/* Explode a random fraction of the player's ammo: */
		ammo_exploding = rand_num(pp->p_ammo);

		/* Determine the type and amount of detonation: */
		expl_charge = rand_num(ammo_exploding + 1);
		if (pp->p_ammo == 0)
			/* Ignore the no-ammo case: */
			expl_charge = expl_type = 0;
		else if (ammo_exploding >= pp->p_ammo - 1) {
			/* Maximal explosions always appear as slime: */
			expl_charge = pp->p_ammo;
			expl_type = SLIME;
		} else {
			/*
			 * Figure out the best effective explosion
			 * type to use, given the amount of charge
			 */
			int btype, stype;
			for (btype = MAXBOMB - 1; btype > 0; btype--)
				if (expl_charge >= shot_req[btype])
					break;
			for (stype = MAXSLIME - 1; stype > 0; stype--)
				if (expl_charge >= slime_req[stype])
					break;
			/* Pick the larger of the bomb or slime: */
			if (btype >= 0 && stype >= 0) {
				if (shot_req[btype] > slime_req[btype])
					btype = -1;
			}
			if (btype >= 0)  {
				expl_type = shot_type[btype];
				expl_charge = shot_req[btype];
			} else
				expl_type = SLIME;
		}

		if (expl_charge > 0) {
			char buf[BUFSIZ];

			/* Detonate: */
			(void) add_shot(expl_type, pp->p_y, pp->p_x,
			    pp->p_face, expl_charge, NULL,
			    TRUE, SPACE);

			/* Explain what the explosion is about. */
			snprintf(buf, sizeof buf, "%s detonated.",
				pp->p_ident->i_name);
			message(ALL_PLAYERS, buf);

			while (pp->p_nboots-- > 0) {
				/* Throw one of the boots away: */
				for (np = Boot; np < &Boot[NBOOTS]; np++)
					if (np->p_flying < 0)
						break;
#ifdef DIAGNOSTIC
				if (np >= &Boot[NBOOTS])
					err(1, "Too many boots");
#endif
				/* Start the boots from where the player is */
				np->p_undershot = FALSE;
				np->p_x = pp->p_x;
				np->p_y = pp->p_y;
				/* Throw for up to 20 steps */
				np->p_flying = rand_num(20);
				np->p_flyx = 2 * rand_num(6) - 5;
				np->p_flyy = 2 * rand_num(6) - 5;
				np->p_over = SPACE;
				np->p_face = BOOT;
				showexpl(np->p_y, np->p_x, BOOT);
			}
		}
		/* No explosion. Leave the player's boots behind. */
		else if (pp->p_nboots > 0) {
			if (pp->p_nboots == 2)
				Maze[pp->p_y][pp->p_x] = BOOT_PAIR;
			else
				Maze[pp->p_y][pp->p_x] = BOOT;
			if (pp->p_undershot)
				fixshots(pp->p_y, pp->p_x,
					Maze[pp->p_y][pp->p_x]);
		}

		/* Any unexploded ammo builds up in the volcano: */
		volcano += pp->p_ammo - expl_charge;

		/* Volcano eruption: */
		if (conf_volcano && rand_num(100) < volcano /
		    conf_volcano_max) {
			/* Erupt near the middle of the map */
			do {
				x = rand_num(WIDTH / 2) + WIDTH / 4;
				y = rand_num(HEIGHT / 2) + HEIGHT / 4;
			} while (Maze[y][x] != SPACE);

			/* Convert volcano charge into lava: */
			(void) add_shot(LAVA, y, x, LEFTS, volcano,
				NULL, TRUE, SPACE);
			volcano = 0;

			/* Tell eveyone what's happening */
			message(ALL_PLAYERS, "Volcano eruption.");
		}

		/* Drone: */
		if (conf_drone && rand_num(100) < 2) {
			/* Find a starting place near the middle of the map: */
			do {
				x = rand_num(WIDTH / 2) + WIDTH / 4;
				y = rand_num(HEIGHT / 2) + HEIGHT / 4;
			} while (Maze[y][x] != SPACE);

			/* Start the drone going: */
			add_shot(DSHOT, y, x, rand_dir(),
				shot_req[conf_mindshot +
				rand_num(MAXBOMB - conf_mindshot)],
				NULL, FALSE, SPACE);
		}

		/* Tell the zapped player's client to shut down. */
		sendcom(pp, ENDWIN, ' ');
		(void) fclose(pp->p_output);

		/* Close up the gap in the Player array: */
		End_player--;
		if (pp != End_player) {
			/* Move the last player into the gap: */
			memcpy(pp, End_player, sizeof *pp);
			outyx(ALL_PLAYERS,
				STAT_PLAY_ROW + 1 + (pp - Player),
				STAT_NAME_COL,
				"%5.2f%c%-10.10s %c",
				pp->p_ident->i_score, stat_char(pp),
				pp->p_ident->i_name, pp->p_ident->i_team);
		}

		/* Erase the last player from the display: */
		cgoto(ALL_PLAYERS, STAT_PLAY_ROW + 1 + Nplayer, STAT_NAME_COL);
		ce(ALL_PLAYERS);
	}
	else {
		/* Zap a monitor */

		/* Close the session: */
		sendcom(pp, ENDWIN, LAST_PLAYER);
		(void) fclose(pp->p_output);

		/* shuffle the monitor table */
		End_monitor--;
		if (pp != End_monitor) {
			memcpy(pp, End_monitor, sizeof *pp);
			outyx(ALL_PLAYERS,
				STAT_MON_ROW + 1 + (pp - Player), STAT_NAME_COL,
				"%5.5s %-10.10s %c", " ",
				pp->p_ident->i_name, pp->p_ident->i_team);
		}

		/* Erase the last monitor in the list */
		cgoto(ALL_PLAYERS,
			STAT_MON_ROW + 1 + (End_monitor - Monitor),
			STAT_NAME_COL);
		ce(ALL_PLAYERS);
	}

	/* Update the file descriptor sets used by select: */
	FD_CLR(savefd, &Fds_mask);
	if (Num_fds == savefd + 1) {
		Num_fds = Socket;
		if (Server_socket > Socket)
			Num_fds = Server_socket;
		for (np = Player; np < End_player; np++)
			if (np->p_fd > Num_fds)
				Num_fds = np->p_fd;
		for (np = Monitor; np < End_monitor; np++)
			if (np->p_fd > Num_fds)
				Num_fds = np->p_fd;
		Num_fds++;
	}
}
Ejemplo n.º 9
0
/*
 * ref;
 *	Refresh the screen
 */
void
ref(PLAYER *pp)
{
	sendcom(pp, REFRESH);
}
Ejemplo n.º 10
0
/*
 * ce:
 *	Clear to the end of the line
 */
void
ce(PLAYER *pp)
{
	sendcom(pp, CLRTOEOL);
}
Ejemplo n.º 11
0
/**
 * Manages the messages submission.
 * \return True in case of success, false instead.
 * [PSR]
 */
int answer() {
	PLAYER *pp;
	int newsock;
	static unsigned long mode; /* Changed from u_long. [PSR] */
	static char name[NAMELEN];
	static char team;
	static int enter_status;
	static unsigned int socklen; /* Edited from static int in order to match accept() parameter. [PSR] */
	static unsigned long machine; /* Edited from u_long in order to match accept() parameter. [PSR] */
	static u_int32_t uid;
	static SOCKET sockstruct;
	char *cp1, *cp2;
	int flags;
	u_int32_t version;
	int i;

# ifdef INTERNET
	socklen = sizeof sockstruct;
# else
	socklen = sizeof sockstruct - 1;
# endif
	errno = 0;
	newsock = accept(main_socket, (struct sockaddr *) &sockstruct, &socklen);
	if (newsock < 0) {
		if (errno == EINTR) {
			return false;
		}
# ifdef LOG
		iso_syslog(LOG_ERR, "accept: %m");
# else
		perror("accept");
# endif
		cleanup(1);
	}

# ifdef INTERNET
	machine = ntohl(((struct sockaddr_in *) &sockstruct)->sin_addr.s_addr);
# else
	if (machine == 0) {
		machine = gethostid();
	}
# endif
	version = htonl((u_int32_t) HUNT_VERSION);
	write_and_push(newsock, (char *) &version, LONGLEN);

	/* Authentication. [PSR] */
#ifdef INTERNET
	if(password_hash!=NULL) { /* A password has been set. [PSR] */
		write_and_push(newsock, &c_auth, SHORTLEN);
		bool auth = false;
		for(i=0; i<MAXATTEMPT && !auth; i++) { /* 3 password attempts. [PSR] */
			safe_read(newsock, &client_psw, (13 + 1) * sizeof(char));
			if(strcmp(client_psw, password_hash)!=0) { /* Authentication failed. New request. [PSR] */
				write_and_push(newsock, &c_auth, SHORTLEN);
			} else { /* Authentication successful. [PSR]*/
				write_and_push(newsock, &c_auth_success, SHORTLEN);
				auth = true;
			}
		}
		if(!auth) {
			write_and_push(newsock, &c_refuse, SHORTLEN);
			safe_close(newsock);
			return false;
		}
	} else { /* No authentication. [PSR] */
		write_and_push(newsock, &c_auth_success, SHORTLEN);
	}
#endif

	safe_read(newsock, (char *) &uid, LONGLEN);
	uid = ntohl((unsigned long) uid);
	safe_read(newsock, name, NAMELEN);
	safe_read(newsock, &team, 1);
	safe_read(newsock, (char *) &enter_status, LONGLEN);
	enter_status = ntohl((unsigned long) enter_status);
	safe_read(newsock, ttyname_glob, NAMELEN);
	safe_read(newsock, (char *) &mode, sizeof mode);
	mode = ntohl(mode);

	/*
	 * Turn off blocking I/O, so a slow or dead terminal won't stop
	 * the game.  All subsequent reads check how many bytes they read.
	 */
	flags = fcntl(newsock, F_GETFL, 0);
	flags |= O_NDELAY;
	(void) fcntl(newsock, F_SETFL, flags);

	/*
	 * Make sure the name contains only printable characters
	 * since we use control characters for cursor control
	 * between driver and player processes
	 */
	for (cp1 = cp2 = name; *cp1 != '\0'; cp1++) {
		if (isprint((unsigned char)*cp1) || *cp1 == ' ') {
			*cp2++ = *cp1;
		}
	}
	*cp2 = '\0';

# ifdef INTERNET
	if (mode == C_MESSAGE) {
		char buf[BUFSIZ + 1];
		int n;

		if (team == ' ') {
			(void) sprintf(buf, "%s: ", name);
		}
		else {
			(void) sprintf(buf, "%s[%c]: ", name, team);
		}
		n = strlen(buf);
		for (pp = player; pp < end_player; pp++) {
			cgoto(pp, HEIGHT, 0);
			outstr(pp, buf, n);
		}
		while ((n = read(newsock, buf, BUFSIZ)) > 0)
		for (pp = player; pp < end_player; pp++) {
			outstr(pp, buf, n);
		}
		for (pp = player; pp < end_player; pp++) {
			ce(pp);
			sendcom(pp, REFRESH);
			sendcom(pp, READY, 0);
			(void) fflush(pp->p_output);
		}
		safe_close(newsock);
		return false;
	}
	else
# endif
# ifdef MONITOR
	if (mode == C_MONITOR) {
		if (end_monitor < &monitor[MAXMON]) {
			pp = end_monitor++;
			i = pp - monitor + MAXPL + 3;
		} else {
			socklen = 0;
			write_and_push(newsock, (char *) &socklen, sizeof socklen);
			safe_close(newsock);
			return false;
		}
	}
	else
# endif
	if (end_player < &player[MAXPL]) {
		pp = end_player++;
		i = pp - player + 3;
	} else {
		socklen = 0;
		write_and_push(newsock, (char *) &socklen, sizeof socklen);
		safe_close(newsock);
		return false;
	}

#ifdef MONITOR
	if (mode == C_MONITOR && team == ' ') {
		team = '*';
	}
#endif
	pp->p_ident = get_ident(machine, uid, name, team);
	pp->p_output = fdopen(newsock, "w");
	pp->p_death[0] = '\0';
	pp->p_fd = newsock;
	fdset[i].fd = newsock;
	fdset[i].events = POLLIN;

	pp->p_y = 0;
	pp->p_x = 0;

# ifdef MONITOR
	if (mode == C_MONITOR) {
		stmonitor(pp);
	}
	else
# endif
	stplayer(pp, enter_status);
	return true;
}
Ejemplo n.º 12
0
/**
 * Initializes a player status.
 * @param[out] newpp The new player to initialize.
 * @param[in] enter_status The enter mode of a player.
 * [PSR]
 */
void stplayer(PLAYER *newpp, int enter_status) {
	int x, y;
	PLAYER *pp;

	nplayer++;

	for (y = 0; y < UBOUND; y++) {
		for (x = 0; x < WIDTH; x++) {
			newpp->p_maze[y][x] = maze[y][x];
		}
	}
	for (; y < DBOUND; y++) {
		for (x = 0; x < LBOUND; x++) {
			newpp->p_maze[y][x] = maze[y][x];
		}
		for (; x < RBOUND; x++) {
			newpp->p_maze[y][x] = SPACE;
		}
		for (; x < WIDTH; x++) {
			newpp->p_maze[y][x] = maze[y][x];
		}
	}
	for (; y < HEIGHT; y++) {
		for (x = 0; x < WIDTH; x++) {
			newpp->p_maze[y][x] = maze[y][x];
		}
	}

	do {
		x = rand_num(WIDTH - 1) + 1;
		y = rand_num(HEIGHT - 1) + 1;
	} while (maze[y][x] != SPACE);
	newpp->p_over = SPACE;
	newpp->p_x = x;
	newpp->p_y = y;
	newpp->p_undershot = false;

# ifdef FLY
	if (enter_status == Q_FLY) {
		newpp->p_flying = rand_num(20);
		newpp->p_flyx = 2 * rand_num(6) - 5;
		newpp->p_flyy = 2 * rand_num(6) - 5;
		newpp->p_face = FLYER;
	}
	else
# endif
	{
# ifdef FLY
		newpp->p_flying = -1;
# endif
		newpp->p_face = rand_dir();
	}
	newpp->p_damage = 0;
	newpp->p_damcap = MAXDAM;
	newpp->p_nchar = 0;
	newpp->p_ncount = 0;
	newpp->p_nexec = 0;
	newpp->p_ammo = ISHOTS;
# ifdef BOOTS
	newpp->p_nboots = 0;
# endif
	if (enter_status == Q_SCAN) {
		newpp->p_scan = SCANLEN;
		newpp->p_cloak = 0;
	} else {
		newpp->p_scan = 0;
		newpp->p_cloak = CLOAKLEN;
	}
	newpp->p_ncshot = 0;

	do {
		x = rand_num(WIDTH - 1) + 1;
		y = rand_num(HEIGHT - 1) + 1;
	} while (maze[y][x] != SPACE);
	maze[y][x] = GMINE;
# ifdef MONITOR
	for (pp = monitor; pp < end_monitor; pp++) {
		check(pp, y, x);
	}
# endif

	do {
		x = rand_num(WIDTH - 1) + 1;
		y = rand_num(HEIGHT - 1) + 1;
	} while (maze[y][x] != SPACE);
	maze[y][x] = MINE;
# ifdef MONITOR
	for (pp = monitor; pp < end_monitor; pp++) {
		check(pp, y, x);
	}
# endif

	(void) sprintf(gen_buf, "%5.2f%c%-10.10s %c", newpp->p_ident->i_score,
			stat_char(newpp), newpp->p_ident->i_name, newpp->p_ident->i_team);
	y = STAT_PLAY_ROW + 1 + (newpp - player);
	for (pp = player; pp < end_player; pp++) {
		if (pp != newpp) {
			char smallbuf[10];

			pp->p_ammo += NSHOTS;
			newpp->p_ammo += NSHOTS;
			cgoto(pp, y, STAT_NAME_COL);
			outstr(pp, gen_buf, STAT_NAME_LEN);
			(void) sprintf(smallbuf, "%3d", pp->p_ammo);
			cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
			outstr(pp, smallbuf, 3);
		}
	}
# ifdef MONITOR
	for (pp = monitor; pp < end_monitor; pp++) {
		cgoto(pp, y, STAT_NAME_COL);
		outstr(pp, gen_buf, STAT_NAME_LEN);
	}
# endif

	drawmaze(newpp);
	drawplayer(newpp, true);
	look(newpp);
# ifdef	FLY
	if (enter_status == Q_FLY) {
		/* Make sure that the position you enter in will be erased */
		showexpl(newpp->p_y, newpp->p_x, FLYER);
	}
# endif
	sendcom(newpp, REFRESH);
	sendcom(newpp, READY, 0);
	(void) fflush(newpp->p_output);
}
Ejemplo n.º 13
0
/*
 * execute:
 *	Execute a single command from a player
 */
void
execute(PLAYER *pp)
{
	char	ch;

	ch = pp->p_cbuf[pp->p_ncount++];

	/* When flying, only allow refresh and quit. */
	if (pp->p_flying >= 0) {
		switch (ch) {
		  case CTRL('L'):
			sendcom(pp, REDRAW);
			break;
		  case 'q':
			(void) strlcpy(pp->p_death, "| Quit |",
			    sizeof pp->p_death);
			break;
		}
		return;
	}

	/* Decode the command character: */
	switch (ch) {
	  case CTRL('L'):
		sendcom(pp, REDRAW);	/* Refresh */
		break;
	  case 'h':
		move_player(pp, LEFTS); /* Move left */
		break;
	  case 'H':
		face(pp, LEFTS);	/* Face left */
		break;
	  case 'j':
		move_player(pp, BELOW); /* Move down */
		break;
	  case 'J':
		face(pp, BELOW);	/* Face down */
		break;
	  case 'k':
		move_player(pp, ABOVE); /* Move up */
		break;
	  case 'K':
		face(pp, ABOVE);	/* Face up */
		break;
	  case 'l':
		move_player(pp, RIGHT);	/* Move right */
		break;
	  case 'L':
		face(pp, RIGHT);	/* Face right */
		break;
	  case 'f':
	  case '1':
		fire(pp, 0);		/* SHOT */
		break;
	  case 'g':
	  case '2':
		fire(pp, 1);		/* GRENADE */
		break;
	  case 'F':
	  case '3':
		fire(pp, 2);		/* SATCHEL */
		break;
	  case 'G':
	  case '4':
		fire(pp, 3);		/* 7x7 BOMB */
		break;
	  case '5':
		fire(pp, 4);		/* 9x9 BOMB */
		break;
	  case '6':
		fire(pp, 5);		/* 11x11 BOMB */
		break;
	  case '7':
		fire(pp, 6);		/* 13x13 BOMB */
		break;
	  case '8':
		fire(pp, 7);		/* 15x15 BOMB */
		break;
	  case '9':
		fire(pp, 8);		/* 17x17 BOMB */
		break;
	  case '0':
		fire(pp, 9);		/* 19x19 BOMB */
		break;
	  case '@':
		fire(pp, 10);		/* 21x21 BOMB */
		break;
	  case 'o':
		fire_slime(pp, 0);	/* SLIME */
		break;
	  case 'O':
		fire_slime(pp, 1);	/* SSLIME */
		break;
	  case 'p':
		fire_slime(pp, 2);	/* large slime */
		break;
	  case 'P':
		fire_slime(pp, 3);	/* very large slime */
		break;
	  case 's':			/* start scanning */
		scan(pp);
		break;
	  case 'c':			/* start cloaking */
		cloak(pp);
		break;
	  case 'q':			/* quit */
		(void) strlcpy(pp->p_death, "| Quit |", sizeof pp->p_death);
		break;
	}
}
Ejemplo n.º 14
0
/*
 * execute:
 *	Execute a single command
 */
void
execute(PLAYER *pp)
{
	char ch;

	ch = pp->p_cbuf[pp->p_ncount++];

#ifdef FLY
	if (pp->p_flying >= 0) {
		switch (ch) {
		  case CTRL('L'):
			sendcom(pp, REDRAW);
			break;
		  case 'q':
			(void) strcpy(pp->p_death, "| Quit |");
			break;
		}
		return;
	}
#endif

	switch (ch) {
	  case CTRL('L'):
		sendcom(pp, REDRAW);
		break;
	  case 'h':
		move_player(pp, LEFTS);
		break;
	  case 'H':
		turn_player(pp, LEFTS);
		break;
	  case 'j':
		move_player(pp, BELOW);
		break;
	  case 'J':
		turn_player(pp, BELOW);
		break;
	  case 'k':
		move_player(pp, ABOVE);
		break;
	  case 'K':
		turn_player(pp, ABOVE);
		break;
	  case 'l':
		move_player(pp, RIGHT);
		break;
	  case 'L':
		turn_player(pp, RIGHT);
		break;
	  case 'f':
	  case '1':
		fire(pp, 0);		/* SHOT */
		break;
	  case 'g':
	  case '2':
		fire(pp, 1);		/* GRENADE */
		break;
	  case 'F':
	  case '3':
		fire(pp, 2);		/* SATCHEL */
		break;
	  case 'G':
	  case '4':
		fire(pp, 3);		/* 7x7 BOMB */
		break;
	  case '5':
		fire(pp, 4);		/* 9x9 BOMB */
		break;
	  case '6':
		fire(pp, 5);		/* 11x11 BOMB */
		break;
	  case '7':
		fire(pp, 6);		/* 13x13 BOMB */
		break;
	  case '8':
		fire(pp, 7);		/* 15x15 BOMB */
		break;
	  case '9':
		fire(pp, 8);		/* 17x17 BOMB */
		break;
	  case '0':
		fire(pp, 9);		/* 19x19 BOMB */
		break;
	  case '@':
		fire(pp, 10);		/* 21x21 BOMB */
		break;
#ifdef OOZE
	  case 'o':
		fire_slime(pp, 0);	/* SLIME */
		break;
	  case 'O':
		fire_slime(pp, 1);	/* SSLIME */
		break;
	  case 'p':
		fire_slime(pp, 2);
		break;
	  case 'P':
		fire_slime(pp, 3);
		break;
#endif
	  case 's':
		scan(pp);
		break;
	  case 'c':
		cloak(pp);
		break;
	  case 'q':
		(void) strcpy(pp->p_death, "| Quit |");
		break;
	}
}
Ejemplo n.º 15
0
int
answer()
{
	PLAYER			*pp;
	int			newsock;
	static u_long		mode;
	static char		name[NAMELEN];
	static char		team;
	static int		enter_status;
	static int		socklen;
	static u_long		machine;
	static u_int32_t	uid;
	static SOCKET		sockstruct;
	char			*cp1, *cp2;
	int			flags;
	u_int32_t		version;
	int			i;

# ifdef INTERNET
	socklen = sizeof sockstruct;
# else
	socklen = sizeof sockstruct - 1;
# endif
	errno = 0;
	newsock = accept(Socket, (struct sockaddr *) &sockstruct, &socklen);
	if (newsock < 0)
	{
		if (errno == EINTR)
			return FALSE;
# ifdef LOG
		syslog(LOG_ERR, "accept: %m");
# else
		perror("accept");
# endif
		cleanup(1);
	}

# ifdef INTERNET
	machine = ntohl(((struct sockaddr_in *) &sockstruct)->sin_addr.s_addr);
# else
	if (machine == 0)
		machine = gethostid();
# endif
	version = htonl((u_int32_t) HUNT_VERSION);
	(void) write(newsock, (char *) &version, LONGLEN);
	(void) read(newsock, (char *) &uid, LONGLEN);
	uid = ntohl((unsigned long) uid);
	(void) read(newsock, name, NAMELEN);
	(void) read(newsock, &team, 1);
	(void) read(newsock, (char *) &enter_status, LONGLEN);
	enter_status = ntohl((unsigned long) enter_status);
	(void) read(newsock, Ttyname, NAMELEN);
	(void) read(newsock, (char *) &mode, sizeof mode);
	mode = ntohl(mode);

	/*
	 * Turn off blocking I/O, so a slow or dead terminal won't stop
	 * the game.  All subsequent reads check how many bytes they read.
	 */
	flags = fcntl(newsock, F_GETFL, 0);
	flags |= O_NDELAY;
	(void) fcntl(newsock, F_SETFL, flags);

	/*
	 * Make sure the name contains only printable characters
	 * since we use control characters for cursor control
	 * between driver and player processes
	 */
	for (cp1 = cp2 = name; *cp1 != '\0'; cp1++)
		if (isprint((unsigned char)*cp1) || *cp1 == ' ')
			*cp2++ = *cp1;
	*cp2 = '\0';

# ifdef INTERNET
	if (mode == C_MESSAGE) {
		char	buf[BUFSIZ + 1];
		int	n;

		if (team == ' ')
			(void) sprintf(buf, "%s: ", name);
		else
			(void) sprintf(buf, "%s[%c]: ", name, team);
		n = strlen(buf);
		for (pp = Player; pp < End_player; pp++) {
			cgoto(pp, HEIGHT, 0);
			outstr(pp, buf, n);
		}
		while ((n = read(newsock, buf, BUFSIZ)) > 0)
			for (pp = Player; pp < End_player; pp++)
				outstr(pp, buf, n);
		for (pp = Player; pp < End_player; pp++) {
			ce(pp);
			sendcom(pp, REFRESH);
			sendcom(pp, READY, 0);
			(void) fflush(pp->p_output);
		}
		(void) close(newsock);
		return FALSE;
	}
	else
# endif
# ifdef MONITOR
	if (mode == C_MONITOR)
		if (End_monitor < &Monitor[MAXMON]) {
			pp = End_monitor++;
			i = pp - Monitor + MAXPL + 3;
		} else {
			socklen = 0;
			(void) write(newsock, (char *) &socklen,
				sizeof socklen);
			(void) close(newsock);
			return FALSE;
		}
	else
# endif
		if (End_player < &Player[MAXPL]) {
			pp = End_player++;
			i = pp - Player + 3;
		} else {
			socklen = 0;
			(void) write(newsock, (char *) &socklen,
				sizeof socklen);
			(void) close(newsock);
			return FALSE;
		}

#ifdef MONITOR
	if (mode == C_MONITOR && team == ' ')
		team = '*';
#endif
	pp->p_ident = get_ident(machine, uid, name, team);
	pp->p_output = fdopen(newsock, "w");
	pp->p_death[0] = '\0';
	pp->p_fd = newsock;
	fdset[i].fd = newsock;
	fdset[i].events = POLLIN;

	pp->p_y = 0;
	pp->p_x = 0;

# ifdef MONITOR
	if (mode == C_MONITOR)
		stmonitor(pp);
	else
# endif
		stplayer(pp, enter_status);
	return TRUE;
}
Ejemplo n.º 16
0
/*
 * moveshots:
 *	Move the shots already in the air, taking explosions into account
 */
void
moveshots(void)
{
    BULLET	*bp, *next;
    PLAYER	*pp;
    int	x, y;
    BULLET	*blist;

    rollexpl();
    if (Bullets == NULL)
        goto no_bullets;

    /*
     * First we move through the bullet list conf_bulspd times, looking
     * for things we may have run into.  If we do run into
     * something, we set up the explosion and disappear, checking
     * for damage to any player who got in the way.
     */

    /* Move the list to a working list */
    blist = Bullets;
    Bullets = NULL;

    /* Work with bullets on the working list (blist) */
    for (bp = blist; bp != NULL; bp = next) {
        next = bp->b_next;

        x = bp->b_x;
        y = bp->b_y;

        /* Un-draw the bullet on all screens: */
        Maze[y][x] = bp->b_over;
        check(ALL_PLAYERS, y, x);

        /* Decide how to move the bullet: */
        switch (bp->b_type) {

        /* Normal, atomic bullets: */
        case SHOT:
        case GRENADE:
        case SATCHEL:
        case BOMB:
            if (move_normal_shot(bp)) {
                /* Still there: put back on the active list */
                bp->b_next = Bullets;
                Bullets = bp;
            }
            break;

        /* Slime bullets that explode into slime on impact: */
        case SLIME:
            if (bp->b_expl || move_normal_shot(bp)) {
                /* Still there: put back on the active list */
                bp->b_next = Bullets;
                Bullets = bp;
            }
            break;

        /* Drones that wander about: */
        case DSHOT:
            if (move_drone(bp)) {
                /* Still there: put back on the active list */
                bp->b_next = Bullets;
                Bullets = bp;
            }
            break;

        /* Other/unknown: */
        default:
            /* Place it back on the active list: */
            bp->b_next = Bullets;
            Bullets = bp;
            break;
        }
    }

    /* Again, hang the Bullets list off `blist' and work with that: */
    blist = Bullets;
    Bullets = NULL;
    for (bp = blist; bp != NULL; bp = next) {
        next = bp->b_next;
        /* Is the bullet exploding? */
        if (!bp->b_expl) {
            /*
             * Its still flying through the air.
             * Put it back on the bullet list.
             */
            save_bullet(bp);

            /* All the monitors can see the bullet: */
            for (pp = Monitor; pp < End_monitor; pp++)
                check(pp, bp->b_y, bp->b_x);

            /* All the scanning players can see the drone: */
            if (bp->b_type == DSHOT)
                for (pp = Player; pp < End_player; pp++)
                    if (pp->p_scan >= 0)
                        check(pp, bp->b_y, bp->b_x);
        } else {
            /* It is exploding. Check what we hit: */
            chkshot(bp, next);
            /* Release storage for the destroyed bullet: */
            free(bp);
        }
    }

    /* Re-draw all the players: (in case a bullet wiped them out) */
    for (pp = Player; pp < End_player; pp++)
        Maze[pp->p_y][pp->p_x] = pp->p_face;

no_bullets:

    /* Move flying boots through the air: */
    for (pp = Boot; pp < &Boot[NBOOTS]; pp++)
        if (pp->p_flying >= 0)
            move_flyer(pp);

    /* Move flying players through the air: */
    for (pp = Player; pp < End_player; pp++) {
        if (pp->p_flying >= 0)
            move_flyer(pp);
        /* Flush out the explosions: */
        sendcom(pp, REFRESH);
        look(pp);
    }

    /* Flush out and synchronise all the displays: */
    sendcom(ALL_PLAYERS, REFRESH);
}
Ejemplo n.º 17
0
/*
 * move_player:
 *	Try to move player 'pp' in direction 'dir'.
 */
static void
move_player(PLAYER *pp, int dir)
{
	PLAYER	*newp;
	int	x, y;
	FLAG	moved;
	BULLET	*bp;

	y = pp->p_y;
	x = pp->p_x;

	switch (dir) {
	  case LEFTS:
		x--;
		break;
	  case RIGHT:
		x++;
		break;
	  case ABOVE:
		y--;
		break;
	  case BELOW:
		y++;
		break;
	}

	moved = FALSE;

	/* What would the player move over: */
	switch (Maze[y][x]) {
	  /* Players can move through spaces and doors, no problem: */
	  case SPACE:
	  case DOOR:
		moved = TRUE;
		break;
	  /* Can't move through walls: */
	  case WALL1:
	  case WALL2:
	  case WALL3:
	  case WALL4:
	  case WALL5:
		break;
	  /* Moving over a mine - try to pick it up: */
	  case MINE:
	  case GMINE:
		if (dir == pp->p_face)
			/* facing it: 2% chance of trip */
			pickup(pp, y, x, conf_ptrip_face, Maze[y][x]);
		else if (opposite(dir, pp->p_face))
			/* facing away: 95% chance of trip */
			pickup(pp, y, x, conf_ptrip_back, Maze[y][x]);
		else
			/* facing sideways: 50% chance of trip */
			pickup(pp, y, x, conf_ptrip_side, Maze[y][x]);
		/* Remove the mine: */
		Maze[y][x] = SPACE;
		moved = TRUE;
		break;
	  /* Moving into a bullet: */
	  case SHOT:
	  case GRENADE:
	  case SATCHEL:
	  case BOMB:
	  case SLIME:
	  case DSHOT:
		/* Find which bullet: */
		bp = is_bullet(y, x);
		if (bp != NULL)
			/* Detonate it: */
			bp->b_expl = TRUE;
		/* Remove it: */
		Maze[y][x] = SPACE;
		moved = TRUE;
		break;
	  /* Moving into another player: */
	  case LEFTS:
	  case RIGHT:
	  case ABOVE:
	  case BELOW:
		if (dir != pp->p_face)
			/* Can't walk backwards/sideways into another player: */
			sendcom(pp, BELL);
		else {
			/* Stab the other player */
			newp = play_at(y, x);
			checkdam(newp, pp, pp->p_ident, conf_stabdam, KNIFE);
		}
		break;
	  /* Moving into a player flying overhead: */
	  case FLYER:
		newp = play_at(y, x);
		message(newp, "Oooh, there's a short guy waving at you!");
		message(pp, "You couldn't quite reach him!");
		break;
	  /* Picking up a boot, or two: */
	  case BOOT_PAIR:
		pp->p_nboots++;
	  case BOOT:
		pp->p_nboots++;
		for (newp = Boot; newp < &Boot[NBOOTS]; newp++) {
			if (newp->p_flying < 0)
				continue;
			if (newp->p_y == y && newp->p_x == x) {
				newp->p_flying = -1;
				if (newp->p_undershot)
					fixshots(y, x, newp->p_over);
			}
		}
		if (pp->p_nboots == 2)
			message(pp, "Wow!  A pair of boots!");
		else
			message(pp, "You can hobble around on one boot.");
		Maze[y][x] = SPACE;
		moved = TRUE;
		break;
	}

	/* Can the player be moved? */
	if (moved) {
		/* Check the gun status: */
		if (pp->p_ncshot > 0)
			if (--pp->p_ncshot == conf_maxncshot)
				outyx(pp, STAT_GUN_ROW, STAT_VALUE_COL, " ok");
		/* Check for bullets flying past: */
		if (pp->p_undershot) {
			fixshots(pp->p_y, pp->p_x, pp->p_over);
			pp->p_undershot = FALSE;
		}
		/* Erase the player: */
		drawplayer(pp, FALSE);
		/* Save under: */
		pp->p_over = Maze[y][x];
		/* Move the player: */
		pp->p_y = y;
		pp->p_x = x;
		/* Draw the player in their new position */
		drawplayer(pp, TRUE);
	}
}