AI Player version 4 - this should be the easy beginner ai

origin
stpohle 23 years ago
parent 619f9be99e
commit be14223281

@ -25,7 +25,7 @@
#define SPECIAL_LIQUID_NUMUSE 5 #define SPECIAL_LIQUID_NUMUSE 5
#define SPECIAL_DESTROY_NUMUSE 5 #define SPECIAL_DESTROY_NUMUSE 5
#define START_BOMBS 5 #define START_BOMBS 1
#define START_RANGE 2 #define START_RANGE 2
#define START_SPEED 16 #define START_SPEED 16
#define SPEEDMUL 1.2 #define SPEEDMUL 1.2

@ -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 */ /* bomberclone.h */
#ifndef _BOMBERCLONE_H_ #ifndef _BOMBERCLONE_H_
@ -165,6 +165,13 @@ struct __menu {
// int type; // could be visible / disabled / grayed ?? should avoid -2 trick // int type; // could be visible / disabled / grayed ?? should avoid -2 trick
} typedef _menu; } typedef _menu;
struct __airunaway {
signed char dir;
signed char bestdir;
} typedef _airunaway;
extern _bomberclone bman; extern _bomberclone bman;
extern Uint32 timestamp; extern Uint32 timestamp;
extern int debug; extern int debug;
@ -249,7 +256,7 @@ extern int ai_checkpos (_player * pl, _point * pos);
extern int ai_findnearbombs (_point pos); extern int ai_findnearbombs (_point pos);
extern int ai_findbestbombdir (_point pos, int dir, int range); extern int ai_findbestbombdir (_point pos, int dir, int range);
extern int ai_bombpoints (_point pos, 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_checkfield (int x, int y);
extern int ai_easyrunaway (_point p); extern int ai_easyrunaway (_point p);

@ -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 */ /* single player */
#include "basic.h" #include "basic.h"
@ -66,7 +66,7 @@ single_game_new ()
int int
ai_checkfield (int x, int y) 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,8 +74,11 @@ ai_checkfield (int x, int y)
int int
ai_easyrunaway (_point p) ai_easyrunaway (_point p)
{ {
int i, done = 0, dir = 0; int i,
_point pos[4], m[4]; done = 0,
dir = 0;
_point pos[4],
m[4];
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
pos[i] = p; pos[i] = p;
@ -107,7 +110,8 @@ ai_easyrunaway (_point p)
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
/* check if we are still in the game field */ /* 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) 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; pos[i].x = pos[i].y = -1;
if (pos[i].x != -1 && pos[i].y != -1) { if (pos[i].x != -1 && pos[i].y != -1) {
@ -116,11 +120,15 @@ ai_easyrunaway (_point p)
done = 0; done = 0;
/* check the field left and right beside */ /* check the field left and right beside */
if (i == left || i == right) { 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))) 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); dir |= (1 << i);
} }
else { 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))) 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); dir |= (1 << i);
} }
pos[i].x += m[i].x; pos[i].x += m[i].x;
@ -134,12 +142,27 @@ ai_easyrunaway (_point p)
}; };
/* give the run away direction */ /* give the run away direction
int the return value:
*/
_airunaway
ai_runawayfrom (_point p, int nearbomb, signed char norecursive) ai_runawayfrom (_point p, int nearbomb, signed char norecursive)
{ {
int i, done = 0, dir = 0, nbomb, tdir, _i; int i,
_point pos[4], m[4]; 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++) { for (i = 0; i < 4; i++) {
pos[i] = p; pos[i] = p;
@ -168,16 +191,26 @@ ai_runawayfrom (_point p, int nearbomb, signed char norecursive)
/* test if we just have to move to the side */ /* test if we just have to move to the side */
if (!norecursive) if (!norecursive)
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
if (ai_findnearbombs (pos[i]) == 0) if (ai_checkfield (pos[i].x, pos[i].y) && ai_findnearbombs (pos[i]) == 0) {
dir |= (1 << i); bdirpoints = 0;
res.bestdir = i;
res.dir |= (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 */ /* test the possible ways */
while (!done) { while (!done) {
done = 1; done = 1;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
/* check if we are still in the game field */ /* 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) 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; pos[i].x = pos[i].y = -1;
if (pos[i].x != -1 && pos[i].y != -1) { if (pos[i].x != -1 && pos[i].y != -1) {
@ -185,45 +218,66 @@ ai_runawayfrom (_point p, int nearbomb, signed char norecursive)
if (ai_checkfield (pos[i].x, pos[i].y)) { if (ai_checkfield (pos[i].x, pos[i].y)) {
done = 0; done = 0;
/* check the field left and right beside */ /* check the field left and right beside */
if (i == left || i == right) { for (j = 0; j < 4; j++)
if (ai_checkfield (pos[i].x, pos[i].y - 1) || ai_checkfield (pos[i].x, pos[i].y + 1)) if (((i == left || i == right) && (j == up || j == down)) ||
dir |= (1 << i); ((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 { else {
if (ai_checkfield (pos[i].x - 1, pos[i].y) || ai_checkfield (pos[i].x + 1, pos[i].y)) // printf ("-%d ", i);
dir |= (1 << i); c = -1;
} }
pos[i].x += m[i].x;
pos[i].y += m[i].y;
} }
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
} }
} }
}
if (norecursive == 0) {// to prevent from invinite loops pos[i].x += m[i].x;
for (i = 0; i < 4; i ++) pos[i].y += m[i].y;
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));
} }
} }
return dir; /* 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 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 int
ai_bombpoints (_point pos, int range) ai_bombpoints (_point pos, int range)
{ {
@ -233,7 +287,8 @@ ai_bombpoints (_point pos, int range)
_point p, _point p,
m; 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++) { for (d = 0; d < 4; d++) {
switch (d) { switch (d) {
case (left): case (left):
@ -261,8 +316,11 @@ ai_bombpoints (_point pos, int range)
p.y += m.y; 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++; 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;
} }
} }
@ -277,46 +335,83 @@ ai_bombpoints (_point pos, int range)
int int
ai_findbestbombdir (_point pos, int dir, int range) 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, int d,
bestd = dir; done = 0,
_point m, j,
p; 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) { switch (d) {
case (left): case (left):
m.x = -1; m[d].x = -1;
m.y = 0; m[d].y = 0;
break; break;
case (right): case (right):
m.x = 1; m[d].x = 1;
m.y = 0; m[d].y = 0;
break; break;
case (up): case (up):
m.x = 0; m[d].x = 0;
m.y = -1; m[d].y = -1;
break;
case (down):
m.x = 0;
m.y = 1;
break; break;
default: default:
m.x = 0; m[d].x = 0;
m.y = 0; m[d].y = 1;
break; break;
} }
}
p.x = pos.x + m.x; while (!done) {
p.y = pos.y + m.y; done = 1;
points[d] = ai_bombpoints (p, range); for (d = 0; d < 5; d++) {
if (points[d] > points[bestd])
bestd = 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 (points[bestd] <= points[4] && points[4] != 0) if (maxpoints < points[d])
bestd = 4; maxpoints = points[d];
}
}
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; return bestd;
} }
@ -329,6 +424,7 @@ ai_findnearbombs (_point pos)
{ {
int d, int d,
res = 0, // result if there is a bomb res = 0, // result if there is a bomb
done = 0; done = 0;
_point m[4]; // direction addition _point m[4]; // direction addition
_point dist[4]; // to check every direction (on three ways) _point dist[4]; // to check every direction (on three ways)
@ -412,21 +508,26 @@ ai_checkpos (_player * pl, _point * pos)
/* random choose direction */ /* random choose direction */
int int
ai_choosedir (int dir, int nearbomb, int oldpos) { ai_choosedir (int dir, int nearbomb, int oldpos)
{
int rdir[4]; int rdir[4];
int bdir[4*3]; int bdir[4 * 3];
int i, rnr, bnr; int i,
rnr,
bnr;
for (rnr = bnr= i = 0; i < 4; i++) { for (rnr = bnr = i = 0; i < 4; i++) {
if ((dir & (1 << i)) != 0) { if ((dir & (1 << i)) != 0) {
rdir[rnr] = i; rdir[rnr] = i;
rnr++; rnr++;
} }
if (((nearbomb & (DIRM_up+DIRM_down)) != 0) && ((dir & (1 << i)) != 0) && (i == left || i == right) && i != ai_invertdir (oldpos)) { if (((nearbomb & (DIRM_up + DIRM_down)) != 0) && ((dir & (1 << i)) != 0)
&& (i == left || i == right) && i != ai_invertdir (oldpos)) {
bdir[bnr] = i; bdir[bnr] = i;
bnr++; bnr++;
} }
if (((nearbomb & (DIRM_left+DIRM_right)) != 0) && ((dir & (1 << i)) != 0) && (i == down || i == up) && i != ai_invertdir (oldpos)) { if (((nearbomb & (DIRM_left + DIRM_right)) != 0) && ((dir & (1 << i)) != 0)
&& (i == down || i == up) && i != ai_invertdir (oldpos)) {
bdir[bnr] = i; bdir[bnr] = i;
bnr++; bnr++;
} }
@ -445,23 +546,30 @@ ai_choosedir (int dir, int nearbomb, int oldpos) {
int int
ai_invertdir (int dir) { ai_invertdir (int dir)
{
int idir; int idir;
switch (dir) { switch (dir) {
case (left): case (left):
idir = right; break; idir = right;
break;
case (right): case (right):
idir = left; break; idir = left;
break;
case (down): case (down):
idir = up; break; idir = up;
break;
default: default:
idir = down; break; idir = down;
break;
} }
return idir; return idir;
}; };
int ai_checknewpos (_point pos,int d) { int
ai_checknewpos (_point pos, int d)
{
_point m; _point m;
switch (d) { switch (d) {
case (left): case (left):
@ -519,7 +627,7 @@ single_playergame ()
for (p = 0; p < MAX_PLAYERS; p++) for (p = 0; p < MAX_PLAYERS; p++)
bman.players[p].state = 0; bman.players[p].state = 0;
single_create_ai (5); single_create_ai (7);
single_game_new (); single_game_new ();
gfx_game_init (); gfx_game_init ();
game_loop (); game_loop ();
@ -534,8 +642,10 @@ single_loop ()
int p; int p;
_player *pl; _player *pl;
_point plpos; _point plpos;
int nearbomb = 0, bestbdir, int nearbomb = 0,
bestbdir,
i; i;
_airunaway rawdir;
for (p = 0; p < MAX_PLAYERS; p++) for (p = 0; p < MAX_PLAYERS; p++)
if (p != bman.p_nr && PS_IS_alife (bman.players[p].state)) { if (p != bman.p_nr && PS_IS_alife (bman.players[p].state)) {
@ -550,16 +660,16 @@ single_loop ()
nearbomb = ai_findnearbombs (plpos); nearbomb = ai_findnearbombs (plpos);
if (nearbomb == 0) { // no bombs found if (nearbomb == 0) { // no bombs found
bestbdir = ai_findbestbombdir (plpos, pl->d, pl->range); bestbdir = ai_findbestbombdir (plpos, pl->d, pl->range);
if (bestbdir >= 4) { if (bestbdir & DIRM_under) {
if (ai_easyrunaway (plpos) != 0) if (ai_easyrunaway (plpos) != 0)
player_drop_bomb (p); player_drop_bomb (p);
} }
else if (bestbdir == -1) { else if (bestbdir == 0) {
pl->d = s_random (4); pl->d = s_random (4);
pl->m = 1; pl->m = 1;
} }
else { else {
pl->d = bestbdir; pl->d = ai_choosedir (bestbdir, 0, pl->d);
pl->m = 1; pl->m = 1;
} }
if (!ai_checknewpos (plpos, pl->d)) if (!ai_checknewpos (plpos, pl->d))
@ -567,10 +677,17 @@ single_loop ()
} }
else { else {
// bombs in the near found // bombs in the near found
if ((i = ai_runawayfrom (plpos, nearbomb, 0)) != 0) { // printf ("P%d,%d ", plpos.x, plpos.y);
pl->d = ai_choosedir (i, nearbomb, pl->d); // we have to make a choice.. do it 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; pl->m = 1;
} }
// printf (" d:%d m:%d\n", pl->d, pl->m);
} }
} }
player_ilness_loop (p); player_ilness_loop (p);

@ -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.. sysfunc.c - this file hold some routines for the system functions..
like d_delay like d_delay
*/ */
@ -170,3 +170,16 @@ s_dirfilter (_direntry * dirstart, signed char dirflags)
return newstart; 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;
}

@ -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 */ /* include some system near functions */
#ifndef _SYSFUNC_H_ #ifndef _SYSFUNC_H_
@ -20,6 +20,7 @@ struct __direntry {
extern void s_delay (int ms); extern void s_delay (int ms);
extern int s_random (int maxnr); extern int s_random (int maxnr);
extern char *s_gethomedir (); extern char *s_gethomedir ();
extern int s_countbits (int nbomb, int nr);
extern _direntry *s_getdir (char *path); extern _direntry *s_getdir (char *path);
extern _direntry *s_dirfilter (_direntry *dirstart, signed char dirflags); extern _direntry *s_dirfilter (_direntry *dirstart, signed char dirflags);

@ -14,4 +14,4 @@ sh configure --cache-file="$cache" \
$* $*
exec make $* exec make $*
exec strip src/bomberclone.exe

Loading…
Cancel
Save