|
|
@ -1,4 +1,4 @@
|
|
|
|
/* $Id: map.c,v 1.20 2004/01/07 23:04:32 patty21 Exp $ */
|
|
|
|
/* $Id: map.c,v 1.21 2004/02/07 23:51:17 stpohle Exp $ */
|
|
|
|
/* map handling, like generate and load maps. */
|
|
|
|
/* map handling, like generate and load maps. */
|
|
|
|
|
|
|
|
|
|
|
|
#include "bomberclone.h"
|
|
|
|
#include "bomberclone.h"
|
|
|
@ -40,6 +40,11 @@ map_new (char *filename)
|
|
|
|
y;
|
|
|
|
y;
|
|
|
|
FILE *fmap;
|
|
|
|
FILE *fmap;
|
|
|
|
signed char old_maptype = map.type;
|
|
|
|
signed char old_maptype = map.type;
|
|
|
|
|
|
|
|
int pl_cnt, pl;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* initialize the start_point array in the _map struct */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map_init_start_points();
|
|
|
|
|
|
|
|
|
|
|
|
if (filename) {
|
|
|
|
if (filename) {
|
|
|
|
fmap = fopen (filename, "r");
|
|
|
|
fmap = fopen (filename, "r");
|
|
|
@ -97,6 +102,32 @@ map_new (char *filename)
|
|
|
|
for (y = 0; y < MAX_FIELDSIZE_Y; y++)
|
|
|
|
for (y = 0; y < MAX_FIELDSIZE_Y; y++)
|
|
|
|
map.bfield[x][y] = 0;
|
|
|
|
map.bfield[x][y] = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* count the number of players on this map so we know how many starting points
|
|
|
|
|
|
|
|
* to find
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pl_cnt = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (pl = 0; pl < MAX_PLAYERS; pl++) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (PS_IS_used (players[pl].state)) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pl_cnt++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* identify possible starting positions for players and store them in the
|
|
|
|
|
|
|
|
* start_point array in the _map struct. This will always succeed. If
|
|
|
|
|
|
|
|
* it cannot find starting points within the tolerance, it first attempts
|
|
|
|
|
|
|
|
* to create start points within the tolerence and otherwise lowers the
|
|
|
|
|
|
|
|
* tolerence until it can satisfy the proper number of start points.
|
|
|
|
|
|
|
|
* eventually the tolerence reaches 0, so it can, in the worst case, start
|
|
|
|
|
|
|
|
* all players at the same start point.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map_find_and_add_start_points(pl_cnt - map_num_defined_start_points(), MAP_POSITION_TOLERENCE);
|
|
|
|
|
|
|
|
|
|
|
|
/* Set the Playerinformation */
|
|
|
|
/* Set the Playerinformation */
|
|
|
|
map_set_playerposition (fmap != NULL);
|
|
|
|
map_set_playerposition (fmap != NULL);
|
|
|
|
|
|
|
|
|
|
|
@ -159,6 +190,10 @@ map_genrandom ()
|
|
|
|
map.field[x][y].frame = 0.0f;
|
|
|
|
map.field[x][y].frame = 0.0f;
|
|
|
|
map.field[x][y].special = FT_nothing;
|
|
|
|
map.field[x][y].special = FT_nothing;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* set the corners of the map to be valid start points */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map_ensure_corner_start_points();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -336,65 +371,95 @@ map_set_playerposition (int usermap)
|
|
|
|
int pl,
|
|
|
|
int pl,
|
|
|
|
ready,
|
|
|
|
ready,
|
|
|
|
maxtry;
|
|
|
|
maxtry;
|
|
|
|
|
|
|
|
int all_players_set = 1;
|
|
|
|
|
|
|
|
|
|
|
|
d_printf ("map_set_playerposition\n");
|
|
|
|
d_printf ("map_set_playerposition\n");
|
|
|
|
|
|
|
|
|
|
|
|
/* try to set every player on a good place */
|
|
|
|
/* This is the new code that will set every player in a starting point
|
|
|
|
maxtry = 300;
|
|
|
|
* It should never fail, but if it does, it will fall through to the old method
|
|
|
|
ready = 0;
|
|
|
|
*/
|
|
|
|
while (!ready && maxtry-- > 0) {
|
|
|
|
|
|
|
|
ready = 1;
|
|
|
|
|
|
|
|
for (pl = 0; pl < MAX_PLAYERS; pl++)
|
|
|
|
|
|
|
|
if (PS_IS_used (players[pl].state) && (PLX (pl) < 0 || PLY (pl) < 0)) {
|
|
|
|
|
|
|
|
/* set player */
|
|
|
|
|
|
|
|
ready = 0;
|
|
|
|
|
|
|
|
map_set_player_way1 (pl);
|
|
|
|
|
|
|
|
map_playerpos_check (pl);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* every player which is still not set .. set now and delete some normal stones */
|
|
|
|
for (pl = 0; pl < MAX_PLAYERS; pl++) {
|
|
|
|
maxtry = 200;
|
|
|
|
if (PS_IS_used(players[pl].state)) {
|
|
|
|
ready = 0;
|
|
|
|
map_place_player(pl);
|
|
|
|
while (!ready && maxtry-- > 0) {
|
|
|
|
}
|
|
|
|
ready = 1;
|
|
|
|
|
|
|
|
for (pl = 0; pl < MAX_PLAYERS; pl++)
|
|
|
|
|
|
|
|
if (PS_IS_used (players[pl].state) && (PLX (pl) < 0 || PLY (pl) < 0)) {
|
|
|
|
|
|
|
|
/* set player */
|
|
|
|
|
|
|
|
ready = 0;
|
|
|
|
|
|
|
|
map_set_player_way2 (pl, 0);
|
|
|
|
|
|
|
|
if (maxtry > 50)
|
|
|
|
|
|
|
|
map_playerpos_check (pl);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* try another way for setting the players */
|
|
|
|
|
|
|
|
maxtry = 200;
|
|
|
|
/* test to see if all players are placed */
|
|
|
|
ready = 0;
|
|
|
|
|
|
|
|
while (!ready && maxtry-- > 0) {
|
|
|
|
for (pl = 0; pl < MAX_PLAYERS; pl++) {
|
|
|
|
ready = 1;
|
|
|
|
|
|
|
|
for (pl = 0; pl < MAX_PLAYERS; pl++)
|
|
|
|
if ((PS_IS_used(players[pl].state))
|
|
|
|
if (PS_IS_used (players[pl].state) && (PLX (pl) < 0 || PLY (pl) < 0)) {
|
|
|
|
&& ((players[pl].pos.x < 0) || (players[pl].pos.y < 0))) {
|
|
|
|
/* set player */
|
|
|
|
|
|
|
|
ready = 0;
|
|
|
|
all_players_set = 0;
|
|
|
|
map_set_player_way2 (pl, 1);
|
|
|
|
break;
|
|
|
|
if (maxtry > 50)
|
|
|
|
}
|
|
|
|
map_playerpos_check (pl);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* if a used player is not set at a valid start point, fall into the old mode */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!all_players_set) {
|
|
|
|
|
|
|
|
|
|
|
|
/* every player who is still not set ... let them die before they
|
|
|
|
d_fatal("Using old player set method. This should not happen.\n");
|
|
|
|
* can play put a warning on the screen */
|
|
|
|
|
|
|
|
maxtry = 0; // mark our warning
|
|
|
|
/* try to set every player on a good place */
|
|
|
|
for (pl = 0; pl < MAX_PLAYERS; pl++)
|
|
|
|
maxtry = 300;
|
|
|
|
if (PS_IS_used (players[pl].state) && (PLX (pl) < 0 || PLY (pl) < 0)) {
|
|
|
|
ready = 0;
|
|
|
|
PLX (pl) = 0.0;
|
|
|
|
while (!ready && maxtry-- > 0) {
|
|
|
|
PLY (pl) = 0.0;
|
|
|
|
ready = 1;
|
|
|
|
maxtry = 1;
|
|
|
|
for (pl = 0; pl < MAX_PLAYERS; pl++)
|
|
|
|
|
|
|
|
if (PS_IS_used (players[pl].state) && (PLX (pl) < 0 || PLY (pl) < 0)) {
|
|
|
|
|
|
|
|
/* set player */
|
|
|
|
|
|
|
|
ready = 0;
|
|
|
|
|
|
|
|
map_set_player_way1 (pl);
|
|
|
|
|
|
|
|
map_playerpos_check (pl);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (maxtry)
|
|
|
|
|
|
|
|
d_fatal ("Not All Player could been set\n");
|
|
|
|
/* every player which is still not set .. set now and delete some normal stones */
|
|
|
|
|
|
|
|
maxtry = 200;
|
|
|
|
|
|
|
|
ready = 0;
|
|
|
|
|
|
|
|
while (!ready && maxtry-- > 0) {
|
|
|
|
|
|
|
|
ready = 1;
|
|
|
|
|
|
|
|
for (pl = 0; pl < MAX_PLAYERS; pl++)
|
|
|
|
|
|
|
|
if (PS_IS_used (players[pl].state) && (PLX (pl) < 0 || PLY (pl) < 0)) {
|
|
|
|
|
|
|
|
/* set player */
|
|
|
|
|
|
|
|
ready = 0;
|
|
|
|
|
|
|
|
map_set_player_way2 (pl, 0);
|
|
|
|
|
|
|
|
if (maxtry > 50)
|
|
|
|
|
|
|
|
map_playerpos_check (pl);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* try another way for setting the players */
|
|
|
|
|
|
|
|
maxtry = 200;
|
|
|
|
|
|
|
|
ready = 0;
|
|
|
|
|
|
|
|
while (!ready && maxtry-- > 0) {
|
|
|
|
|
|
|
|
ready = 1;
|
|
|
|
|
|
|
|
for (pl = 0; pl < MAX_PLAYERS; pl++)
|
|
|
|
|
|
|
|
if (PS_IS_used (players[pl].state) && (PLX (pl) < 0 || PLY (pl) < 0)) {
|
|
|
|
|
|
|
|
/* set player */
|
|
|
|
|
|
|
|
ready = 0;
|
|
|
|
|
|
|
|
map_set_player_way2 (pl, 1);
|
|
|
|
|
|
|
|
if (maxtry > 50)
|
|
|
|
|
|
|
|
map_playerpos_check (pl);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* every player who is still not set ... let them die before they
|
|
|
|
|
|
|
|
* can play put a warning on the screen */
|
|
|
|
|
|
|
|
maxtry = 0; // mark our warning
|
|
|
|
|
|
|
|
for (pl = 0; pl < MAX_PLAYERS; pl++)
|
|
|
|
|
|
|
|
if (PS_IS_used (players[pl].state) && (PLX (pl) < 0 || PLY (pl) < 0)) {
|
|
|
|
|
|
|
|
PLX (pl) = 0.0;
|
|
|
|
|
|
|
|
PLY (pl) = 0.0;
|
|
|
|
|
|
|
|
maxtry = 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (maxtry)
|
|
|
|
|
|
|
|
d_fatal ("Not All Player could been set\n");
|
|
|
|
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#undef PLX
|
|
|
|
#undef PLX
|
|
|
@ -529,3 +594,503 @@ map_load (FILE * fmap)
|
|
|
|
|
|
|
|
|
|
|
|
fclose (fmap);
|
|
|
|
fclose (fmap);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* This is called for randomly generated maps. It clears out each corner of the map
|
|
|
|
|
|
|
|
* to make sure that the 4 corners are legal start points.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
|
|
map_ensure_corner_start_points ()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* make sure all the corners are empty as well as the 1 field in the Y direction
|
|
|
|
|
|
|
|
* and one in the X direction
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* top left corner is safe start point */
|
|
|
|
|
|
|
|
map.field[1][1].type = FT_nothing;
|
|
|
|
|
|
|
|
map.field[1][2].type = FT_nothing;
|
|
|
|
|
|
|
|
map.field[2][1].type = FT_nothing;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map_add_start_point(1, 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* bottom left corner is safe start point */
|
|
|
|
|
|
|
|
map.field[1][map.size.y - 2].type = FT_nothing;
|
|
|
|
|
|
|
|
map.field[1][map.size.y - 3].type = FT_nothing;
|
|
|
|
|
|
|
|
map.field[2][map.size.y - 2].type = FT_nothing;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map_add_start_point(1, map.size.y - 2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* top right corner is safe start point */
|
|
|
|
|
|
|
|
map.field[map.size.x - 2][1].type = FT_nothing;
|
|
|
|
|
|
|
|
map.field[map.size.x - 3][1].type = FT_nothing;
|
|
|
|
|
|
|
|
map.field[map.size.x - 2][2].type = FT_nothing;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map_add_start_point(map.size.x - 2, 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* bottom right corner is safe start point */
|
|
|
|
|
|
|
|
map.field[map.size.x - 2][map.size.y - 2].type = FT_nothing;
|
|
|
|
|
|
|
|
map.field[map.size.x - 2][map.size.y - 3].type = FT_nothing;
|
|
|
|
|
|
|
|
map.field[map.size.x - 3][map.size.y - 2].type = FT_nothing;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map_add_start_point(map.size.x - 2, map.size.y - 2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* initializes all the start points for the map to (-1,-1) and their used flag to 0 */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
|
|
map_init_start_points()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_PLAYERS; i++) {
|
|
|
|
|
|
|
|
map.start_point[i].pos.x = -1;
|
|
|
|
|
|
|
|
map.start_point[i].pos.y = -1;
|
|
|
|
|
|
|
|
map.start_point[i].used = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* blindly sets (x,y) as the idx'th start point in the map */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
|
|
map_set_start_point(int idx, int x, int y)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
map.start_point[idx].pos.x = x;
|
|
|
|
|
|
|
|
map.start_point[idx].pos.y = y;
|
|
|
|
|
|
|
|
return idx;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* checks to see if all start points have been set, if not, sets (x,y) as a possible start point
|
|
|
|
|
|
|
|
* returns 0 on successful set, -1 on failure
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
|
|
map_add_start_point(int x, int y)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* find the first unset start point */
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_PLAYERS; i++) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((map.start_point[i].pos.x == -1) && (map.start_point[i].pos.y == -1)) {
|
|
|
|
|
|
|
|
map_set_start_point(i, x, y);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* if all start points are already set, do nothing and return -1 */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* returns 0 if (x,y) is not already set as a start point in the current map, nonzero otherwise */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
|
|
map_is_start_point(int x, int y)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_PLAYERS; i++) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((map.start_point[i].pos.x == x) && (map.start_point[i].pos.y == y))
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* returns the number of start points set in the current map */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
|
|
map_num_defined_start_points()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int pts = 0;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_PLAYERS; i++) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((map.start_point[i].pos.x != -1) && (map.start_point[i].pos.y != -1))
|
|
|
|
|
|
|
|
pts++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return pts;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* checks if the start point (x, y) is far enough away from all the other start points
|
|
|
|
|
|
|
|
* returns 1 if it is far enough, 0 otherwise
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
|
|
map_check_start_point(int x, int y, int tol)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
int dx, dy;
|
|
|
|
|
|
|
|
float dist;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_PLAYERS; i++) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((map.start_point[i].pos.x != -1) && (map.start_point[i].pos.y != -1)) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dx = map.start_point[i].pos.x - x;
|
|
|
|
|
|
|
|
dy = map.start_point[i].pos.y - y;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dist = sqrt(dx * dx + dy * dy);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (dist < tol)
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* checks to see if there is an available start point and if (x, y) is sufficiently far from all
|
|
|
|
|
|
|
|
* defined start points and adds (x, y) as a start point if the conditions are met.
|
|
|
|
|
|
|
|
* returns 1 on success, 0 on failure
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
|
|
map_check_and_add_start_point(int x, int y, int tol)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if ((map_num_defined_start_points() < MAX_PLAYERS) && (map_check_start_point(x, y, tol))) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map_add_start_point(x, y);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* locates and adds num start points to the current map. returns the number of start points added. */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
|
|
map_find_and_add_start_points(int num, int tol)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int x;
|
|
|
|
|
|
|
|
int y;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
int added = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while ((added < num) && (tol >= 0)) {
|
|
|
|
|
|
|
|
for (x = 0; x < map.size.x; x++) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (y = 0; y < map.size.y; y++) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (map_is_possible_start_point(x, y)) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
added += map_check_and_add_start_point(x, y, tol);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < num - added; i++) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
added += map_create_and_add_start_point(tol);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tol--;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* printf("Minimum Tolerance: %d\n", tol + 1); */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return added;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* returns 1 if (x,y) is a feasible start point such that the player can safely lay a bomb and not die
|
|
|
|
|
|
|
|
* otherwise returns 0. Note: this is a quick check only checking immediately adjacent fields. It will not
|
|
|
|
|
|
|
|
* check secondary adjacencies, however, the idea is that when looking for possible start poitns, it will be run
|
|
|
|
|
|
|
|
* on every FT_nothing field so it will catch the secondary adjacencies when they become primary adjacencies
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
|
|
map_is_possible_start_point(int x, int y)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int x_ok_pos;
|
|
|
|
|
|
|
|
int x_ok_neg;
|
|
|
|
|
|
|
|
int y_ok_pos;
|
|
|
|
|
|
|
|
int y_ok_neg;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int x_adj = 0;
|
|
|
|
|
|
|
|
int y_adj = 0;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* if (x, y) is not FT_nothing, this is not a valid start point */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (map.field[x][y].type != FT_nothing) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
x_ok_pos = (x < map.size.x - 2) ? 1:0;
|
|
|
|
|
|
|
|
x_ok_neg = (x > 1) ? 1:0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
y_ok_pos = (y < map.size.y - 2) ? 1:0;
|
|
|
|
|
|
|
|
y_ok_neg = (y > 1) ? 1:0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* calculate the number of adjacent FT_nothing fields in the X and Y directions */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 1; i < 4; i++) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (x_ok_pos) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (map.field[x+i][y].type == FT_nothing) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
x_adj++;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
x_ok_pos = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (x_ok_neg) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (map.field[x-i][y].type == FT_nothing) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
x_adj++;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
x_ok_neg = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (y_ok_pos) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (map.field[x][y+i].type == FT_nothing) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
y_adj++;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
y_ok_pos = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (y_ok_neg) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (map.field[x][y-i].type == FT_nothing) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
y_adj++;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
y_ok_neg = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((x_adj >= 3) || (y_adj >= 3)) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((x_adj >= 1) && (y_adj >= 1)) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* alters the map to create another start point at least tol units from any other
|
|
|
|
|
|
|
|
* start point. returns 1 on success, 0 on failure
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
|
|
map_create_and_add_start_point(int tol)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int x;
|
|
|
|
|
|
|
|
int y;
|
|
|
|
|
|
|
|
int dx;
|
|
|
|
|
|
|
|
int dy;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int init_x;
|
|
|
|
|
|
|
|
int init_y;
|
|
|
|
|
|
|
|
int end_x;
|
|
|
|
|
|
|
|
int end_y;
|
|
|
|
|
|
|
|
int step_x;
|
|
|
|
|
|
|
|
int step_y;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* this changes how we traverse the map when looking for a place to put
|
|
|
|
|
|
|
|
* a start point. this is so all the start points don't get stuck in one
|
|
|
|
|
|
|
|
* part of the map if the map is large enough
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_random(100) % 2) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
init_x = 0;
|
|
|
|
|
|
|
|
end_x = map.size.x;
|
|
|
|
|
|
|
|
step_x = 1;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
init_x = map.size.x - 1;
|
|
|
|
|
|
|
|
end_x = -1;
|
|
|
|
|
|
|
|
step_x = -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_random(100) % 2) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
init_y = 0;
|
|
|
|
|
|
|
|
end_y = map.size.y;
|
|
|
|
|
|
|
|
step_y = 1;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
init_y = map.size.y - 1;
|
|
|
|
|
|
|
|
end_y = -1;
|
|
|
|
|
|
|
|
step_y = -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* first try only FT_nothing fields as start points */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (x = init_x; x != end_x; x += step_x) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (y = init_y; y != end_y; y+= step_y) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((map.field[x][y].type == FT_nothing) && (map_check_start_point(x, y, tol))) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dx = (x >= map.size.x - 2) ? -1:1;
|
|
|
|
|
|
|
|
dy = (y >= map.size.y - 2) ? -1:1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((map_is_removable_field(x+dx, y)) && (map_is_removable_field(x, y+dy))) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* printf("Creating Start Point (%d, %d).\n", x, y); */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map.field[x][y].type = FT_nothing;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map.field[x+dx][y].type = FT_nothing;
|
|
|
|
|
|
|
|
map.field[x][y+dy].type = FT_nothing;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map_add_start_point(x, y);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* if we get here we didn't find a useful FT_nothing field, so check the FT_stone
|
|
|
|
|
|
|
|
* fields
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (x = init_x; x != end_x; x += step_x) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (y = init_y; y != end_y; y+= step_y) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((map.field[x][y].type == FT_stone) && (map_check_start_point(x, y, tol))) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dx = (x >= map.size.x - 2) ? -1:1;
|
|
|
|
|
|
|
|
dy = (y >= map.size.y - 2) ? -1:1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((map_is_removable_field(x+dx, y)) && (map_is_removable_field(x, y+dy))) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* printf("Creating Start Point (%d, %d).\n", x, y); */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map.field[x][y].type = FT_nothing;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map.field[x+dx][y].type = FT_nothing;
|
|
|
|
|
|
|
|
map.field[x][y+dy].type = FT_nothing;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map_add_start_point(x, y);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* if we get to this point, we tried every field that we want to turn into a
|
|
|
|
|
|
|
|
* start point, so we return 0 indicating failure
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* checks the type of the field at (x, y). if it is something we can remove without
|
|
|
|
|
|
|
|
* drastically altering the map (that is to say, not a FT_tunnel or FT_block) returns
|
|
|
|
|
|
|
|
* 1, returns 0 if this is not a field that we want to alter
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
|
|
map_is_removable_field(int x, int y)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if ((map.field[x][y].type == FT_nothing) || (map.field[x][y].type == FT_stone)) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* sets the players[pl] initial position to one of the start_points found in the map
|
|
|
|
|
|
|
|
* randomly selects the start point so the same players don't always start near each
|
|
|
|
|
|
|
|
* other
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
|
|
map_place_player(int pl)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int index;
|
|
|
|
|
|
|
|
int start_points;
|
|
|
|
|
|
|
|
int idx;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
start_points = map_num_defined_start_points();
|
|
|
|
|
|
|
|
index = (s_random(MAX_PLAYERS) + 1) % start_points;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < start_points; i++) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
idx = (index + i) % start_points;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((!map.start_point[idx].used) && (map.start_point[idx].pos.x != -1)
|
|
|
|
|
|
|
|
&& (map.start_point[idx].pos.y != -1)) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
players[pl].pos.x = map.start_point[idx].pos.x;
|
|
|
|
|
|
|
|
players[pl].pos.y = map.start_point[idx].pos.y;
|
|
|
|
|
|
|
|
map.start_point[idx].used = 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* this will randomly select a start point, check to see if it is a safe place to
|
|
|
|
|
|
|
|
* respawn the player, and then set their position. It cannot fail unless there is
|
|
|
|
|
|
|
|
* no start point possible on the map (which would prevent the game from ever starting)
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* note: this is not used yet, but could be used to respawn players instead of the old
|
|
|
|
|
|
|
|
* method
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
|
|
map_respawn_player(int pl)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int x;
|
|
|
|
|
|
|
|
int y;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
x = s_random (map.size.x - 2) + 1;
|
|
|
|
|
|
|
|
y = s_random (map.size.y - 2) + 1;
|
|
|
|
|
|
|
|
} while (!map_is_possible_start_point(x, y));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
players[pl].pos.x = x;
|
|
|
|
|
|
|
|
players[pl].pos.y = y;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|