You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bomberclone/src/field.c

385 lines
12 KiB

/* $Id: field.c,v 1.14 2003/05/07 21:28:12 stpohle Exp $ */
/* field.c - procedures which are needed to control the field */
#include <stdlib.h>
#include <SDL.h>
#include "bomberclone.h"
#include "gfx.h"
void
draw_stone (int x, int y)
{
_field *stone = &bman.field[x][y];
SDL_Rect dest,
src;
SDL_Surface *srcimg;
int i,
d;
src.w = dest.w = gfx.block.x;
src.h = dest.h = gfx.block.y;
dest.x = x * gfx.block.x + gfx.offset.x;
dest.y = y * gfx.block.y + gfx.offset.y;
src.x = 0;
if (stone->frame == 0 || stone->type != FT_stone) {
srcimg = gfx.field[stone->type].image;
src.y = 0;
}
else {
if (stone->frameto == 0) {
if (stone->frame < gfx.field[stone->type].frames) {
stone->frame++;
stone->frameto = ANI_STONETIMEOUT;
}
}
if (stone->frameto > 0)
stone->frameto--;
if (stone->frame < gfx.field[stone->type].frames) {
src.y = stone->frame * gfx.block.y;
srcimg = gfx.field[stone->type].image;
}
else {
src.y = 0;
srcimg = gfx.field[FT_nothing].image;
}
}
if (stone->frame > 0)
SDL_BlitSurface (gfx.field[FT_nothing].image, NULL, gfx.screen, &dest);
SDL_BlitSurface (srcimg, &src, gfx.screen, &dest);
// draw explosions if there is any
for (d = 0, i = 0; d < 4; d++)
if (stone->ex[d].count > 0) {
i = 1; // mark that there is already an explosion
draw_fire (x, y, d, -1);
}
if (i == 0) // we don't have to do this anymore because this was happend in draw_fire
gfx_AddUpdateRect (dest.x, dest.y, dest.w, dest.h);
return;
};
void
draw_field ()
{
int x,
y;
for (x = 0; x < bman.fieldsize.x; x++)
for (y = 0; y < bman.fieldsize.y; y++)
draw_stone (x, y);
};
/* read from an open file map, determine field.x and field.y
and fill the field.
(# correspond to a bloc and @ correspond to a stone,
an espace is nothing ' '
% are commentary at the beginning of the map */
void
field_load (FILE * map)
{
size_t length;
char *currentline;
char tmp[MAX_FIELDSIZE_X];
int sizex = 0;
int sizey = 0;
int i;
int d;
while ((currentline = fgets (tmp, MAX_FIELDSIZE_X, map))) {
length = strlen (currentline);
if (currentline[0] == '%')
continue;
/* now each line correspond to the field */
else {
for (i = 0; i < length; i++) {
switch (currentline[i]) {
case '#':
bman.field[i][sizey].type = FT_block;
break;
case '@':
bman.field[i][sizey].type = FT_stone;
break;
case ' ':
bman.field[i][sizey].type = FT_nothing;
default:
break;
}
for (d = 0; d < 4; d++)
bman.field[i][sizey].ex[d].frame = bman.field[i][sizey].ex[d].count = 0;
bman.field[i][sizey].ex_nr = -1;
bman.field[i][sizey].frame = 0;
bman.field[i][sizey].frameto = 0;
bman.field[i][sizey].special = FT_nothing;
}
sizey++;
if (sizex < length)
sizex = length;
}
}
bman.fieldsize.x = sizex - 1;
bman.fieldsize.y = sizey;
/* darw the border so we know everything is right */
for (i = 0; i < bman.fieldsize.x; i++)
bman.field[i][0].type = bman.field[i][bman.fieldsize.y-1].type = FT_block;
for (i = 0; i < bman.fieldsize.y; i++)
bman.field[0][i].type = bman.field[bman.fieldsize.x-1][i].type = FT_block;
}
/* will set the playerposition but in a way that we won't start on a block */
/* i am just too lazy to write this all again and again */
#define PLX bman.players[i].pos.x
#define PLY bman.players[i].pos.y
void field_set_playerposition (int usermap) {
int p, dist, i,j , mx, my, dx = 0, dy = 0;
char txt[255];
p = 50;
dist = 8;
while (p == 50) {
p = 0;
dist--;
for (i = 0; (p < 50 && i < MAX_PLAYERS);) {
if (usermap) {
int maxloop = 0;
while (maxloop < 200 && (PLX == -1 || PLY == -1)) {
maxloop++;
PLX = s_random (bman.fieldsize.x - 2) + 1;
PLY = s_random (bman.fieldsize.y - 2) + 1;
for (dx = 10, dy = 10, j = 0; (j < i && j < MAX_PLAYERS && (dx > 1 || dy > 1)); j++) { /* is ther any other player */
dx = PLX - bman.players[j].pos.x;
if (dx < 0) dx = - dx;
dy = PLY - bman.players[j].pos.y;
if (dy < 0) dy = - dy;
}
/* check if there is no block */
if ((dx > 1 || dy > 1) && ((bman.field[PLX][PLY].type != FT_block && maxloop > 100) ||
bman.field[PLX][PLY].type == FT_nothing)) {
/* get (up or down) dx and (left or right) dy */
dx = s_random (2);
if (dx == 0)
dx = -1;
dy = s_random (2);
if (dy == 0)
dy = -1;
/* first check if there is and free place for us */
if (!((bman.field[PLX+dx][PLY].type != FT_block && maxloop > 100) ||
bman.field[PLX+dx][PLY].type == FT_nothing))
dx = -dx;
if (!((bman.field[PLX+dx][PLY].type != FT_block && maxloop > 100) ||
bman.field[PLX+dx][PLY].type == FT_nothing))
PLX = -1;
if (!((bman.field[PLX][PLY+dy].type != FT_block && maxloop > 100) ||
bman.field[PLX][PLY+dy].type == FT_nothing))
dy = -dy;
if (!((bman.field[PLX][PLY+dy].type != FT_block && maxloop > 100) ||
bman.field[PLX][PLY+dy].type == FT_nothing))
PLY = -1;
}
else {
PLX = -1;
PLY = -1;
}
/* make some space */
if (PLX != -1 && PLY != -1) {
bman.field[PLX][PLY].type = FT_nothing;
bman.field[PLX+dx][PLY].type = FT_nothing;
bman.field[PLX][PLY+dy].type = FT_nothing;
}
}
}
if (PLX == -1 || PLY == -1) {
/* we could not set all fields or we don't run on a usermap */
if (usermap) {
sprintf (txt,"Not all players could be set (Pl:%d)", i);
menu_displaymessage ("MAP - ERROR",txt);
}
/* now there will be some fields deleted */
PLX = 2 * (s_random ((bman.fieldsize.x - 1) / 2)) + 1;
PLY = 2 * (s_random ((bman.fieldsize.y - 1) / 2)) + 1;
bman.field[PLX][PLY].type = FT_nothing;
dx = s_random (4); // bit 1 = up/down bit 2 = left/right
/* up and down */
if (((dx & 1) == 0 && PLX > 1) || PLX >= bman.fieldsize.x - 2)
bman.field[PLX-1][PLY].type = FT_nothing;
else
bman.field[PLX+1][PLY].type = FT_nothing;
/* left and right */
if (((dx & 2) == 0 && PLY > 1) || PLY >= bman.fieldsize.y - 2)
bman.field[PLX][PLY-1].type = FT_nothing;
else
bman.field[PLX][PLY+1].type = FT_nothing;
}
mx = my = 100;
for (j = 0; j <= i; j++) { /* search smalest distance */
dy = PLY - bman.players[j].pos.y;
dx = PLX - bman.players[j].pos.x;
if (dy < 0)
dy = -dy;
if (dx < 0)
dx = -dx;
if (mx > dx && i != j)
mx = dx;
if (my > dy && i != j)
my = dy;
}
if (mx > dist || my > dist)
i++;
else
p++;
}
}
for (i = 0; i < MAX_PLAYERS; i++) {
PLX = PLX << 8;
PLY = PLY << 8;
}
};
#undef PLX
#undef PLY
void
field_new (char *filename)
{
int x,
y,
d;
FILE *fmap;
float fkt;
int nb_try;
if(filename)
{
fmap = fopen (filename, "r");
/* if we can't open the given filename for any reason, reverting
to default value else, load the file */
if (fmap)
field_load (fmap);
}
else
{
fmap = NULL;
}
/* this is the item factor we multiply it with this so we know
how much items we want in the game */
fkt = ((float)(bman.fieldsize.x * bman.fieldsize.y))/(25.0 * 17.0);
// Clean and create the field //
if (fmap == NULL) {
/* if we can't load the map check first the fieldsize settings */
if (bman.fieldsize.x < MIN_FIELDSIZE_X)
bman.fieldsize.x = MIN_FIELDSIZE_X;
if (bman.fieldsize.x > MAX_FIELDSIZE_X)
bman.fieldsize.x = MAX_FIELDSIZE_X;
for (x = 0; x < bman.fieldsize.x; x++)
for (y = 0; y < bman.fieldsize.y; y++) {
if ((y == 0) || (y == bman.fieldsize.y - 1))
bman.field[x][y].type = FT_block;
else if ((x == 0) || (x == bman.fieldsize.x - 1))
bman.field[x][y].type = FT_block;
else if (((x & 1) == 0) && ((y & 1) == 0))
bman.field[x][y].type = FT_block;
else {
// create random field
if ((s_random (256) & 3) == 0)
bman.field[x][y].type = FT_nothing;
else
bman.field[x][y].type = FT_stone;
}
for (d = 0; d < 4; d++)
bman.field[x][y].ex[d].frame = bman.field[x][y].ex[d].count = 0;
bman.field[x][y].ex_nr = -1;
bman.field[x][y].frame = 0;
bman.field[x][y].frameto = 0;
bman.field[x][y].special = FT_nothing;
}
}
/* Set the Playerinformation */
field_set_playerposition (fmap != NULL);
nb_try = 100; // to prevent infinite loops (maybe there are no stones)
/* put the fire powerups in the field */
for (d = 0, x = 0, y = 0; d < GAME_SPECIAL_ITEMFIRE * fkt; d++) {
while (bman.field[x][y].type != FT_stone || bman.field[x][y].special != FT_nothing) {
x = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.x - 1);
y = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.y - 1);
nb_try--;
if (nb_try < 0)
break;
}
bman.field[x][y].special = FT_fire;
x = y = 0;
}
nb_try = 100;
/* put the bomb powerups in the field */
for (d = 0, x = 0, y = 0; d < GAME_SPECIAL_ITEMBOMB * fkt; d++) {
while (bman.field[x][y].type != FT_stone || bman.field[x][y].special != FT_nothing) {
x = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.x - 1);
y = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.y - 1);
nb_try--;
if (nb_try < 0)
break;
}
bman.field[x][y].special = FT_bomb;
x = y = 0;
}
nb_try = 100;
/* put the shoe powerup in the field */
for (d = 0, x = 0, y = 0; d < GAME_SPECIAL_ITEMSHOE * fkt; d++) {
while (bman.field[x][y].type != FT_stone || bman.field[x][y].special != FT_nothing) {
x = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.x - 1);
y = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.y - 1);
nb_try--;
if (nb_try < 0)
break;
}
bman.field[x][y].special = FT_shoe;
x = y = 0;
}
nb_try = 100;
/* put the death ?powerups? in the field */
for (d = 0, x = 0, y = 0; d < GAME_SPECIAL_ITEMDEATH * fkt; d++) {
while (bman.field[x][y].type != FT_stone || bman.field[x][y].special != FT_nothing) {
x = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.x - 1);
y = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.y - 1);
nb_try--;
if (nb_try < 0)
break;
}
bman.field[x][y].special = FT_death;
x = y = 0;
}
}