diff --git a/src/basic.h b/src/basic.h index e946d4a..c81675f 100644 --- a/src/basic.h +++ b/src/basic.h @@ -25,7 +25,7 @@ #define SPECIAL_LIQUID_NUMUSE 5 #define SPECIAL_DESTROY_NUMUSE 5 -#define START_BOMBS 5 +#define START_BOMBS 1 #define START_RANGE 2 #define START_SPEED 16 #define SPEEDMUL 1.2 diff --git a/src/bomberclone.h b/src/bomberclone.h index 35613e2..96a706b 100644 --- a/src/bomberclone.h +++ b/src/bomberclone.h @@ -1,4 +1,4 @@ -/* $Id: bomberclone.h,v 1.28 2003/05/28 23:03:21 stpohle Exp $ */ +/* $Id: bomberclone.h,v 1.29 2003/05/29 17:43:37 stpohle Exp $ */ /* bomberclone.h */ #ifndef _BOMBERCLONE_H_ @@ -165,6 +165,13 @@ struct __menu { // int type; // could be visible / disabled / grayed ?? should avoid -2 trick } typedef _menu; + +struct __airunaway { + signed char dir; + signed char bestdir; +} typedef _airunaway; + + extern _bomberclone bman; extern Uint32 timestamp; extern int debug; @@ -249,7 +256,7 @@ extern int ai_checkpos (_player * pl, _point * pos); extern int ai_findnearbombs (_point pos); extern int ai_findbestbombdir (_point pos, int dir, int range); extern int ai_bombpoints (_point pos, int range); -extern int ai_runawayfrom (_point p, int nearbomb, signed char norecursive); +extern _airunaway ai_runawayfrom (_point p, int nearbomb, signed char norecursive); extern int ai_checkfield (int x, int y); extern int ai_easyrunaway (_point p); diff --git a/src/single.c b/src/single.c index 88be807..deede77 100644 --- a/src/single.c +++ b/src/single.c @@ -1,4 +1,4 @@ -/* $Id: single.c,v 1.23 2003/05/29 00:56:48 stpohle Exp $ */ +/* $Id: single.c,v 1.24 2003/05/29 17:43:37 stpohle Exp $ */ /* single player */ #include "basic.h" @@ -66,7 +66,7 @@ single_game_new () int ai_checkfield (int x, int y) { - return (bman.field[x][y].type == FT_nothing && bman.bfield[x][y] == 0); + return ((bman.field[x][y].type == FT_nothing || bman.field[x][y].type == FT_fire || bman.field[x][y].type == FT_shoe || bman.field[x][y].type == FT_bomb ) && bman.bfield[x][y] == 0); } @@ -74,156 +74,210 @@ ai_checkfield (int x, int y) int ai_easyrunaway (_point p) { - int i, done = 0, dir = 0; - _point pos[4], m[4]; - - for (i = 0; i < 4; i++) { - pos[i] = p; + int i, + done = 0, + dir = 0; + _point pos[4], + m[4]; + + for (i = 0; i < 4; i++) { + pos[i] = p; switch (i) { - case (left): - m[i].x = -1; - m[i].y = 0; - break; - case (right): - m[i].x = 1; - m[i].y = 0; - break; - case (up): - m[i].x = 0; - m[i].y = -1; - break; - default: - m[i].x = 0; - m[i].y = 1; - break; + case (left): + m[i].x = -1; + m[i].y = 0; + break; + case (right): + m[i].x = 1; + m[i].y = 0; + break; + case (up): + m[i].x = 0; + m[i].y = -1; + break; + default: + m[i].x = 0; + m[i].y = 1; + break; + } + pos[i].x += m[i].x; + pos[i].y += m[i].y; + } + + /* test the possible ways */ + while (!done) { + done = 1; + + for (i = 0; i < 4; i++) { + /* check if we are still in the game field */ + if (pos[i].x <= 0 || pos[i].y <= 0 || pos[i].x >= bman.fieldsize.x - 1 + || pos[i].y >= bman.fieldsize.y - 1) + pos[i].x = pos[i].y = -1; + + if (pos[i].x != -1 && pos[i].y != -1) { + /* check if this place is free to go to */ + if (ai_checkfield (pos[i].x, pos[i].y)) { + done = 0; + /* check the field left and right beside */ + if (i == left || i == right) { + if (ai_findnearbombs (pos[i]) == 0 + && (ai_checkfield (pos[i].x, pos[i].y - 1) + || ai_checkfield (pos[i].x, pos[i].y + 1))) + dir |= (1 << i); + } + else { + if (ai_findnearbombs (pos[i]) == 0 + && (ai_checkfield (pos[i].x - 1, pos[i].y) + || ai_checkfield (pos[i].x + 1, pos[i].y))) + dir |= (1 << i); + } + pos[i].x += m[i].x; + pos[i].y += m[i].y; + } } - pos[i].x += m[i].x; - pos[i].y += m[i].y; - } + } + } - /* test the possible ways */ - while (!done) { - done = 1; - - for (i = 0; i < 4; i++) { - /* check if we are still in the game field */ - if (pos[i].x <= 0 || pos[i].y <= 0 || pos[i].x >= bman.fieldsize.x-1 || pos[i].y >= bman.fieldsize.y-1) - pos[i].x = pos[i].y = -1; - - if (pos[i].x != -1 && pos[i].y != -1) { - /* check if this place is free to go to */ - if (ai_checkfield (pos[i].x, pos[i].y)) { - done = 0; - /* check the field left and right beside */ - if (i == left || i == right) { - if (ai_findnearbombs (pos[i]) == 0 && (ai_checkfield (pos[i].x, pos[i].y - 1) || ai_checkfield (pos[i].x, pos[i].y + 1))) - dir |= (1 << i); - } - else { - if (ai_findnearbombs (pos[i]) == 0 && (ai_checkfield (pos[i].x - 1, pos[i].y) || ai_checkfield (pos[i].x + 1, pos[i].y))) - dir |= (1 << i); - } - pos[i].x += m[i].x; - pos[i].y += m[i].y; - } - } - } - } - - return dir; + return dir; }; -/* give the run away direction */ -int +/* give the run away direction + the return value: +*/ +_airunaway ai_runawayfrom (_point p, int nearbomb, signed char norecursive) { - int i, done = 0, dir = 0, nbomb, tdir, _i; - _point pos[4], m[4]; - - for (i = 0; i < 4; i++) { - pos[i] = p; + int i, + done = 0, + nbomb, + tdir, + _i, + bdirpoints = 10, + j, + c; + _airunaway res; + _point pos[4], + m[4], + tpos; + + res.dir = 0; + res.bestdir = -1; + + for (i = 0; i < 4; i++) { + pos[i] = p; switch (i) { - case (left): - m[i].x = -1; - m[i].y = 0; - break; - case (right): - m[i].x = 1; - m[i].y = 0; - break; - case (up): - m[i].x = 0; - m[i].y = -1; - break; - default: - m[i].x = 0; - m[i].y = 1; - break; + case (left): + m[i].x = -1; + m[i].y = 0; + break; + case (right): + m[i].x = 1; + m[i].y = 0; + break; + case (up): + m[i].x = 0; + m[i].y = -1; + break; + default: + m[i].x = 0; + m[i].y = 1; + break; + } + pos[i].x += m[i].x; + pos[i].y += m[i].y; + } + + /* test if we just have to move to the side */ + if (!norecursive) + for (i = 0; i < 4; i++) + if (ai_checkfield (pos[i].x, pos[i].y) && ai_findnearbombs (pos[i]) == 0) { + bdirpoints = 0; + res.bestdir = i; + res.dir |= (1 << i); } - pos[i].x += m[i].x; - pos[i].y += m[i].y; - } - /* test if we just have to move to the side */ - if (!norecursive) - for (i = 0; i < 4; i++) - if (ai_findnearbombs (pos[i]) == 0) - dir |= (1 << i); - - /* test the possible ways */ - while (!done) { - done = 1; - - for (i = 0; i < 4; i++) { - /* check if we are still in the game field */ - if (pos[i].x <= 0 || pos[i].y <= 0 || pos[i].x >= bman.fieldsize.x-1 || pos[i].y >= bman.fieldsize.y-1) - pos[i].x = pos[i].y = -1; - - if (pos[i].x != -1 && pos[i].y != -1) { - /* check if this place is free to go to */ - if (ai_checkfield (pos[i].x, pos[i].y)) { - done = 0; - /* check the field left and right beside */ - if (i == left || i == right) { - if (ai_checkfield (pos[i].x, pos[i].y - 1) || ai_checkfield (pos[i].x, pos[i].y + 1)) - dir |= (1 << i); - } - else { - if (ai_checkfield (pos[i].x - 1, pos[i].y) || ai_checkfield (pos[i].x + 1, pos[i].y)) - dir |= (1 << i); - } - pos[i].x += m[i].x; - pos[i].y += m[i].y; - } - } - } - } - - if (norecursive == 0) {// to prevent from invinite loops - for (i = 0; i < 4; i ++) - if ((dir & (1 << i)) != 0) { // test if we can use this direction - pos[0].x = p.x + m[i].x; - pos[0].y = p.y + m[i].y; - if (ai_checkfield (pos[0].x, pos[0].y)) { - nbomb = ai_findnearbombs (pos[0]); - if (nbomb != 0) { // test if this is a useless direction - tdir = ai_runawayfrom (pos[0], nbomb, 1); - _i = ai_invertdir (i); - if (tdir == (1 << _i)) // don't use this direction - dir &= (0xFF - (1 << i)); // delete these direction - } - } - else - dir &= (0xFF - (1 << i)); - } +/* if (!norecursive) { + printf ("%d,%d NB:", p.x, p.y); + d_bitprint (nearbomb, 5); + d_bitprint (res.dir, 4); + } +*/ + /* test the possible ways */ + while (!done) { + done = 1; + + for (i = 0; i < 4; i++) { + /* check if we are still in the game field */ + if (pos[i].x <= 0 || pos[i].y <= 0 || pos[i].x >= bman.fieldsize.x - 1 + || pos[i].y >= bman.fieldsize.y - 1) + pos[i].x = pos[i].y = -1; + + if (pos[i].x != -1 && pos[i].y != -1) { + /* check if this place is free to go to */ + if (ai_checkfield (pos[i].x, pos[i].y)) { + done = 0; + /* check the field left and right beside */ + for (j = 0; j < 4; j++) + if (((i == left || i == right) && (j == up || j == down)) || + ((j == left || j == right) && (i == up || i == down))) { + c = 10; + tpos.x = pos[i].x + m[j].x; + tpos.y = pos[i].y + m[j].y; + if (ai_checkfield (tpos.x, tpos.y)) { + nbomb = ai_findnearbombs (tpos); + c = s_countbits (nbomb, 5); + if (!norecursive) { + tdir = ai_runawayfrom (tpos, nbomb, 1).dir; + _i = ai_invertdir (i); + if (tdir != (1 << _i)) { // usefull direction +// printf ("B%d ", i); + res.dir |= (1 << i); // add this one + } + else { +// printf ("-%d ", i); + c = -1; + } + } + else + res.dir |= (1 << i); + + /* check for the best direction */ +// if (!norecursive) printf ("pts:%d|%d ", bdirpoints, res.bestdir); + if (c != -1 && !norecursive) { + if (c < bdirpoints) { + bdirpoints = c; + res.bestdir = i; + } + else if (bdirpoints != 0 && c == bdirpoints && c < 5 + && s_random (2) == 0) + res.bestdir = i; // random if the points are equal + } + } + } + pos[i].x += m[i].x; + pos[i].y += m[i].y; + } + } + } + } + +/* if (!norecursive) { + d_bitprint (res.dir, 4); + printf ("%d ] ", res.bestdir); + } else { + printf ("(%d,%d NB ", p.x, p.y); + d_bitprint (nearbomb, 5); + d_bitprint (res.dir, 4); + printf (")"); } - - return dir; +*/ + return res; }; -/* count the points for dropping a bomb here */ +/* count the points for dropping a bomb here + this will even count if there is any powerup*/ int ai_bombpoints (_point pos, int range) { @@ -233,7 +287,8 @@ ai_bombpoints (_point pos, int range) _point p, m; - if (bman.field[pos.x][pos.y].type != FT_block && bman.field[pos.x][pos.y].type != FT_stone) { + if (bman.field[pos.x][pos.y].type != FT_block && bman.field[pos.x][pos.y].type != FT_stone + && ai_checkfield (pos.x, pos.y)) { for (d = 0; d < 4; d++) { switch (d) { case (left): @@ -261,14 +316,17 @@ ai_bombpoints (_point pos, int range) p.y += m.y; } - if (bman.field[p.x][p.y].type != FT_nothing && bman.field[p.x][p.y].type != FT_block) + if (bman.field[p.x][p.y].type != FT_nothing && (bman.field[p.x][p.y].type != FT_block || bman.field[p.x][p.y].type == FT_shoe || bman.field[p.x][p.y].type == FT_bomb || bman.field[p.x][p.y].type == FT_fire)) points++; + if (bman.field[p.x][p.y].type == FT_shoe || bman.field[p.x][p.y].type == FT_bomb || + bman.field[p.x][p.y].type == FT_fire) + points += 2; } } - + if (ai_easyrunaway (pos) == 0 || ai_findnearbombs (pos) != 0) points = 0; - + return points; }; @@ -277,46 +335,83 @@ ai_bombpoints (_point pos, int range) int ai_findbestbombdir (_point pos, int dir, int range) { - int points[5] = { 0, 0, 0, 0 }; + int points[5] = { 0, 0, 0, 0, 0 }; int d, - bestd = dir; - _point m, - p; + done = 0, + j, + maxpoints = 0, + bestd; + _point m[4], + p[4]; + + points[4] = ai_bombpoints (pos, range); + + /* fill in the positions */ + for (d = 0; d < 4; d++) { + p[d] = pos; - for (d = 0; d < 5; d++) { switch (d) { case (left): - m.x = -1; - m.y = 0; + m[d].x = -1; + m[d].y = 0; break; case (right): - m.x = 1; - m.y = 0; + m[d].x = 1; + m[d].y = 0; break; case (up): - m.x = 0; - m.y = -1; - break; - case (down): - m.x = 0; - m.y = 1; + m[d].x = 0; + m[d].y = -1; break; default: - m.x = 0; - m.y = 0; + m[d].x = 0; + m[d].y = 1; break; } + } - p.x = pos.x + m.x; - p.y = pos.y + m.y; + while (!done) { + done = 1; - points[d] = ai_bombpoints (p, range); - if (points[d] > points[bestd]) - bestd = d; + for (d = 0; d < 5; d++) { + + if (d < 4) { + p[d].x += m[d].x; + p[d].y += m[d].y; + if (p[d].x > 0 && p[d].y > 0 && p[d].x < bman.fieldsize.x - 1 + && p[d].y < bman.fieldsize.y - 1) { + if (ai_checkfield (p[d].x, p[d].y)) { + /* we are opn a empty field go on with the test */ + done = 0; + j = ai_bombpoints (p[d], range); + if (points[d] < j) + points[d] = j; + } + else /* no empty field */ + p[d].x = p[d].y = -1; + } + } + + if (maxpoints < points[d]) + maxpoints = points[d]; + } } - if (points[bestd] <= points[4] && points[4] != 0) - bestd = 4; + bestd = 0; + for (d = 0; d < 5; d++) + if (points[d] >= (maxpoints-1)) + bestd |= (1 << d); + + /* prevent from turning around */ + if (dir != -1 && (bestd & (0xFF -(1 << ai_invertdir(dir))))) + bestd &= (0xFF - (1 << ai_invertdir(dir))); + + d_printf ("ai_bestbombdir (%d,%d) [%d, %d, %d, %d, %d] = ", pos.x, pos.y, points[0], + points[1], points[2], points[3], points[4]); + if (debug) { + d_bitprint (bestd, 5); + printf ("\n"); + } return bestd; } @@ -329,6 +424,7 @@ ai_findnearbombs (_point pos) { int d, res = 0, // result if there is a bomb + done = 0; _point m[4]; // direction addition _point dist[4]; // to check every direction (on three ways) @@ -412,77 +508,89 @@ ai_checkpos (_player * pl, _point * pos) /* random choose direction */ int -ai_choosedir (int dir, int nearbomb, int oldpos) { - int rdir[4]; - int bdir[4*3]; - int i, rnr, bnr; - - for (rnr = bnr= i = 0; i < 4; i++) { - if ((dir & (1 << i)) != 0) { - rdir[rnr] = i; - rnr++; - } - if (((nearbomb & (DIRM_up+DIRM_down)) != 0) && ((dir & (1 << i)) != 0) && (i == left || i == right) && i != ai_invertdir (oldpos)) { - bdir[bnr] = i; - bnr++; - } - if (((nearbomb & (DIRM_left+DIRM_right)) != 0) && ((dir & (1 << i)) != 0) && (i == down || i == up) && i != ai_invertdir (oldpos)) { - bdir[bnr] = i; - bnr++; - } - } - - if (rnr == 0) - return (s_random (4)); +ai_choosedir (int dir, int nearbomb, int oldpos) +{ + int rdir[4]; + int bdir[4 * 3]; + int i, + rnr, + bnr; + + for (rnr = bnr = i = 0; i < 4; i++) { + if ((dir & (1 << i)) != 0) { + rdir[rnr] = i; + rnr++; + } + if (((nearbomb & (DIRM_up + DIRM_down)) != 0) && ((dir & (1 << i)) != 0) + && (i == left || i == right) && i != ai_invertdir (oldpos)) { + bdir[bnr] = i; + bnr++; + } + if (((nearbomb & (DIRM_left + DIRM_right)) != 0) && ((dir & (1 << i)) != 0) + && (i == down || i == up) && i != ai_invertdir (oldpos)) { + bdir[bnr] = i; + bnr++; + } + } + + if (rnr == 0) + return (s_random (4)); - if (bnr != 0) - i = bdir[s_random (bnr)]; - else - i = rdir[s_random (rnr)]; + if (bnr != 0) + i = bdir[s_random (bnr)]; + else + i = rdir[s_random (rnr)]; - return i; + return i; }; int -ai_invertdir (int dir) { - int idir; - switch (dir) { - case (left): - idir = right; break; - case (right): - idir = left; break; - case (down): - idir = up; break; - default: - idir = down; break; - } - return idir; +ai_invertdir (int dir) +{ + int idir; + switch (dir) { + case (left): + idir = right; + break; + case (right): + idir = left; + break; + case (down): + idir = up; + break; + default: + idir = down; + break; + } + return idir; }; -int ai_checknewpos (_point pos,int d) { - _point m; - switch (d) { - case (left): - m.x = pos.x - 1; - m.y = pos.y; - break; - case (right): - m.x = pos.x + 1; - m.y = pos.y; - break; - case (up): - m.x = pos.x; - m.y = pos.y - 1; - break; - default: - m.x = pos.x; - m.y = pos.y + 1; - break; - } - - return (ai_findnearbombs (m) == 0); +int +ai_checknewpos (_point pos, int d) +{ + _point m; + switch (d) { + case (left): + m.x = pos.x - 1; + m.y = pos.y; + break; + case (right): + m.x = pos.x + 1; + m.y = pos.y; + break; + case (up): + m.x = pos.x; + m.y = pos.y - 1; + break; + default: + m.x = pos.x; + m.y = pos.y + 1; + break; + } + + return (ai_findnearbombs (m) == 0); }; @@ -519,7 +627,7 @@ single_playergame () for (p = 0; p < MAX_PLAYERS; p++) bman.players[p].state = 0; - single_create_ai (5); + single_create_ai (7); single_game_new (); gfx_game_init (); game_loop (); @@ -534,43 +642,52 @@ single_loop () int p; _player *pl; _point plpos; - int nearbomb = 0, bestbdir, + int nearbomb = 0, + bestbdir, i; + _airunaway rawdir; for (p = 0; p < MAX_PLAYERS; p++) if (p != bman.p_nr && PS_IS_alife (bman.players[p].state)) { pl = &bman.players[p]; i = ai_checkpos (pl, &plpos); - + if (!i) /* we're still moving */ pl->m = 1; else { nearbomb = ai_findnearbombs (plpos); if (nearbomb == 0) { // no bombs found - bestbdir = ai_findbestbombdir (plpos, pl->d, pl->range); - if (bestbdir >= 4) { - if (ai_easyrunaway (plpos) != 0) - player_drop_bomb (p); - } - else if (bestbdir == -1) { - pl->d = s_random (4); - pl->m = 1; - } - else { - pl->d = bestbdir; - pl->m = 1; - } - if (!ai_checknewpos (plpos, pl->d)) - pl->m = 0; + bestbdir = ai_findbestbombdir (plpos, pl->d, pl->range); + if (bestbdir & DIRM_under) { + if (ai_easyrunaway (plpos) != 0) + player_drop_bomb (p); + } + else if (bestbdir == 0) { + pl->d = s_random (4); + pl->m = 1; + } + else { + pl->d = ai_choosedir (bestbdir, 0, pl->d); + pl->m = 1; + } + if (!ai_checknewpos (plpos, pl->d)) + pl->m = 0; } else { // bombs in the near found - if ((i = ai_runawayfrom (plpos, nearbomb, 0)) != 0) { - pl->d = ai_choosedir (i, nearbomb, pl->d); // we have to make a choice.. do it - pl->m = 1; - } +// printf ("P%d,%d ", plpos.x, plpos.y); + rawdir = ai_runawayfrom (plpos, nearbomb, 0); + if (rawdir.dir != 0 && rawdir.bestdir == -1) { + pl->d = ai_choosedir (rawdir.dir, nearbomb, pl->d); // we have to make a choice.. do it + pl->m = 1; + } + else if (rawdir.bestdir != -1) { + pl->d = rawdir.bestdir; + pl->m = 1; + } +// printf (" d:%d m:%d\n", pl->d, pl->m); } } player_ilness_loop (p); diff --git a/src/sysfunc.c b/src/sysfunc.c index 8abda9a..6b21f75 100644 --- a/src/sysfunc.c +++ b/src/sysfunc.c @@ -1,4 +1,4 @@ -/* $Id: sysfunc.c,v 1.15 2003/05/20 18:05:30 stpohle Exp $ +/* $Id: sysfunc.c,v 1.16 2003/05/29 17:43:38 stpohle Exp $ sysfunc.c - this file hold some routines for the system functions.. like d_delay */ @@ -170,3 +170,16 @@ s_dirfilter (_direntry * dirstart, signed char dirflags) return newstart; }; + + +/* count the bits ... for directions and so on */ +int s_countbits (int bits, int nr) { + int i, r = 0; + + for (i = nr-1; i >= 0; i--) + if ((bits & (1 << i)) != 0) + r++; + + return r; +} + diff --git a/src/sysfunc.h b/src/sysfunc.h index 2ef14f9..b811f6c 100644 --- a/src/sysfunc.h +++ b/src/sysfunc.h @@ -1,4 +1,4 @@ -/* $Id: sysfunc.h,v 1.5 2003/05/08 14:35:49 stpohle Exp $ */ +/* $Id: sysfunc.h,v 1.6 2003/05/29 17:43:38 stpohle Exp $ */ /* include some system near functions */ #ifndef _SYSFUNC_H_ @@ -20,6 +20,7 @@ struct __direntry { extern void s_delay (int ms); extern int s_random (int maxnr); extern char *s_gethomedir (); +extern int s_countbits (int nbomb, int nr); extern _direntry *s_getdir (char *path); extern _direntry *s_dirfilter (_direntry *dirstart, signed char dirflags); diff --git a/tools/cross-mingw32-linux.sh b/tools/cross-mingw32-linux.sh index f448b3e..69535ba 100755 --- a/tools/cross-mingw32-linux.sh +++ b/tools/cross-mingw32-linux.sh @@ -14,4 +14,4 @@ sh configure --cache-file="$cache" \ $* exec make $* -exec strip src/bomberclone.exe +