|
|
|
@ -1,4 +1,4 @@
|
|
|
|
|
/* $Id: single.c,v 1.20 2003/05/26 20:25:54 stpohle Exp $ */
|
|
|
|
|
/* $Id: single.c,v 1.21 2003/05/28 22:31:47 stpohle Exp $ */
|
|
|
|
|
/* single player */
|
|
|
|
|
|
|
|
|
|
#include "basic.h"
|
|
|
|
@ -70,69 +70,94 @@ ai_checkfield (int x, int y)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* check if we can run away in this direction */
|
|
|
|
|
/* give the run away direction */
|
|
|
|
|
int
|
|
|
|
|
ai_checkrunaway (_point pos, int range, int direction)
|
|
|
|
|
ai_runawayfrom (_point p, int nearbomb, signed char norecursive)
|
|
|
|
|
{
|
|
|
|
|
_point m,
|
|
|
|
|
p;
|
|
|
|
|
int ok = 0,
|
|
|
|
|
i;
|
|
|
|
|
int i, done = 0, dir = 0, nbomb, tdir, _i;
|
|
|
|
|
_point pos[4], m[4];
|
|
|
|
|
|
|
|
|
|
p = pos;
|
|
|
|
|
|
|
|
|
|
switch (direction) {
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
|
pos[i] = p;
|
|
|
|
|
switch (i) {
|
|
|
|
|
case (left):
|
|
|
|
|
m.x = -1;
|
|
|
|
|
m.y = 0;
|
|
|
|
|
m[i].x = -1;
|
|
|
|
|
m[i].y = 0;
|
|
|
|
|
break;
|
|
|
|
|
case (right):
|
|
|
|
|
m.x = 1;
|
|
|
|
|
m.y = 0;
|
|
|
|
|
m[i].x = 1;
|
|
|
|
|
m[i].y = 0;
|
|
|
|
|
break;
|
|
|
|
|
case (up):
|
|
|
|
|
m.x = 0;
|
|
|
|
|
m.y = -1;
|
|
|
|
|
m[i].x = 0;
|
|
|
|
|
m[i].y = -1;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
m.x = 0;
|
|
|
|
|
m.y = 1;
|
|
|
|
|
m[i].x = 0;
|
|
|
|
|
m[i].y = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
pos[i].x += m[i].x;
|
|
|
|
|
pos[i].y += m[i].y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 1; (ok == 0 && i < range && ai_checkfield (p.x, p.y)); i++) {
|
|
|
|
|
p.x += m.x;
|
|
|
|
|
p.y += m.y;
|
|
|
|
|
printf (" - ");
|
|
|
|
|
if (direction == left || direction == right) {
|
|
|
|
|
if (ai_checkfield (p.x, p.y - 1) || ai_checkfield (p.x, p.y + 1))
|
|
|
|
|
ok = 1;
|
|
|
|
|
/* 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 (p.x + 1, p.y) || ai_checkfield (p.x - 1, p.y))
|
|
|
|
|
ok = 1;
|
|
|
|
|
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 (i >= range)
|
|
|
|
|
ok = 1;
|
|
|
|
|
|
|
|
|
|
d_printf ("ai_runaway (pos %d,%d , direction %d) %d\n", pos.x, pos.y, direction, ok);
|
|
|
|
|
|
|
|
|
|
return ok;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
printf ("["); d_bitprint (dir, 4);
|
|
|
|
|
|
|
|
|
|
/* give the run away direction */
|
|
|
|
|
int
|
|
|
|
|
ai_runawayfrom (_point p, int range)
|
|
|
|
|
{
|
|
|
|
|
int d;
|
|
|
|
|
int dir = -1;
|
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (d = 0; (d < 4 && dir == -1); d++)
|
|
|
|
|
if (ai_checkrunaway (p, range, d))
|
|
|
|
|
dir = d;
|
|
|
|
|
d_bitprint (dir, 4); printf ("] ");
|
|
|
|
|
|
|
|
|
|
return dir;
|
|
|
|
|
};
|
|
|
|
@ -181,7 +206,7 @@ ai_bombpoints (_point pos, int range)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ai_runawayfrom (pos, range) == -1)
|
|
|
|
|
if ((ai_runawayfrom (p, 16, 0) == 0) || ai_findnearbombs (p) != 0)
|
|
|
|
|
points = 0;
|
|
|
|
|
|
|
|
|
|
return points;
|
|
|
|
@ -247,7 +272,6 @@ 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)
|
|
|
|
@ -257,13 +281,13 @@ ai_findnearbombs (_point pos)
|
|
|
|
|
case (left):
|
|
|
|
|
m[d].x = -1;
|
|
|
|
|
m[d].y = 0;
|
|
|
|
|
dist[d].x = pos.x + 1;
|
|
|
|
|
dist[d].x = pos.x - 1;
|
|
|
|
|
dist[d].y = pos.y;
|
|
|
|
|
break;
|
|
|
|
|
case (right):
|
|
|
|
|
m[d].x = 1;
|
|
|
|
|
m[d].y = 0;
|
|
|
|
|
dist[d].x = pos.x - 1;
|
|
|
|
|
dist[d].x = pos.x + 1;
|
|
|
|
|
dist[d].y = pos.y;
|
|
|
|
|
break;
|
|
|
|
|
case (up):
|
|
|
|
@ -292,7 +316,7 @@ ai_findnearbombs (_point pos)
|
|
|
|
|
}
|
|
|
|
|
if (bman.field[dist[d].x][dist[d].y].type != FT_nothing)
|
|
|
|
|
dist[d].x = dist[d].y = -1; // don't check no more.
|
|
|
|
|
if (dist[d].x != -1 && dist[d].y != -1) {
|
|
|
|
|
else if (dist[d].x != -1 && dist[d].y != -1) {
|
|
|
|
|
dist[d].x += m[d].x;
|
|
|
|
|
dist[d].y += m[d].y;
|
|
|
|
|
done = 0;
|
|
|
|
@ -307,62 +331,6 @@ ai_findnearbombs (_point pos)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* flee from a bomb in the near */
|
|
|
|
|
int
|
|
|
|
|
ai_fleefrombomb (_point pos, int nearbomb, int range)
|
|
|
|
|
{
|
|
|
|
|
int d = 0,
|
|
|
|
|
dir = -1;
|
|
|
|
|
|
|
|
|
|
if ((nearbomb & 3) != 0) { // bomb is in the same row.. try to go up down
|
|
|
|
|
if (s_random (2) == 0 || (nearbomb & 4) != 0)
|
|
|
|
|
d = 1;
|
|
|
|
|
if (bman.field[pos.x][pos.y + d].type == FT_nothing) {
|
|
|
|
|
if (d == 1)
|
|
|
|
|
dir = down;
|
|
|
|
|
else
|
|
|
|
|
dir = up;
|
|
|
|
|
}
|
|
|
|
|
else if (bman.field[pos.x][pos.y - d].type == FT_nothing) {
|
|
|
|
|
if (d == 1)
|
|
|
|
|
dir = up;
|
|
|
|
|
else
|
|
|
|
|
dir = down;
|
|
|
|
|
}
|
|
|
|
|
else if ((nearbomb & 1) == 0)
|
|
|
|
|
dir = left;
|
|
|
|
|
else if ((nearbomb & 2) == 0)
|
|
|
|
|
dir = right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if ((nearbomb & 12) != 0) { // bomb is updown from us
|
|
|
|
|
if (s_random (2) == 0 || (nearbomb & 1) != 0)
|
|
|
|
|
d = 1;
|
|
|
|
|
if (bman.field[pos.x + d][pos.y].type == FT_nothing) {
|
|
|
|
|
if (d == 1)
|
|
|
|
|
dir = right;
|
|
|
|
|
else
|
|
|
|
|
dir = left;
|
|
|
|
|
}
|
|
|
|
|
else if (bman.field[pos.x - d][pos.y].type == FT_nothing) {
|
|
|
|
|
if (d == 1)
|
|
|
|
|
dir = left;
|
|
|
|
|
else
|
|
|
|
|
dir = right;
|
|
|
|
|
}
|
|
|
|
|
else if ((nearbomb & 4) == 0)
|
|
|
|
|
dir = up;
|
|
|
|
|
else if ((nearbomb & 8) == 0)
|
|
|
|
|
dir = down;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dir == -1)
|
|
|
|
|
dir = s_random (4);
|
|
|
|
|
|
|
|
|
|
return dir;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* check if we are still running and fill out the position
|
|
|
|
|
return == 0 we're still walking ... else we have reached a point */
|
|
|
|
|
int
|
|
|
|
@ -385,46 +353,60 @@ ai_checkpos (_player * pl, _point * pos)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
single_loop ()
|
|
|
|
|
{
|
|
|
|
|
int p;
|
|
|
|
|
_player *pl;
|
|
|
|
|
_point plpos;
|
|
|
|
|
int nearbomb = 0,
|
|
|
|
|
bestbombdir = 0,
|
|
|
|
|
i;
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
d_printf ("single_loop pos:%d,%d nearbomb:%d bestbombdir:%d, checkpos: %d\n", plpos.x,
|
|
|
|
|
plpos.y, nearbomb, bestbombdir, i);
|
|
|
|
|
/* random choose direction */
|
|
|
|
|
int
|
|
|
|
|
ai_choosedir (int dir, int nearbomb, int oldpos) {
|
|
|
|
|
int rdir[4];
|
|
|
|
|
int bdir[4];
|
|
|
|
|
int i, rnr, bnr;
|
|
|
|
|
|
|
|
|
|
if (!i) {
|
|
|
|
|
/* we're still moving */
|
|
|
|
|
pl->m = 1;
|
|
|
|
|
for (rnr = bnr= i = 0; i < 4; i++) {
|
|
|
|
|
if ((dir & (1 << i)) != 0) {
|
|
|
|
|
rdir[rnr] = i;
|
|
|
|
|
rnr++;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
nearbomb = ai_findnearbombs (plpos);
|
|
|
|
|
if (nearbomb == 0) { // no bombs found
|
|
|
|
|
if (((nearbomb & (DIRM_up+DIRM_down)) != 0) && ((dir & (1 << i)) != 0) && (i == left || i == right) && i != ai_invertdir (oldpos)) {
|
|
|
|
|
bdir[bnr] = i;
|
|
|
|
|
bnr++;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// bombs in the near found
|
|
|
|
|
pl->m = 1;
|
|
|
|
|
pl->d = ai_fleefrombomb (plpos, nearbomb, pl->range + 1);
|
|
|
|
|
printf (" %d ", pl->d);
|
|
|
|
|
if (((nearbomb & (DIRM_left+DIRM_right)) != 0) && ((dir & (1 << i)) != 0) && (i == down || i == up) && i != ai_invertdir (oldpos)) {
|
|
|
|
|
bdir[bnr] = i;
|
|
|
|
|
bnr++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
player_ilness_loop (p);
|
|
|
|
|
move_player (p);
|
|
|
|
|
|
|
|
|
|
if (rnr == 0)
|
|
|
|
|
return (s_random (4));
|
|
|
|
|
|
|
|
|
|
if (bnr != 0)
|
|
|
|
|
i = bdir[s_random (bnr)];
|
|
|
|
|
else
|
|
|
|
|
i = rdir[s_random (rnr)];
|
|
|
|
|
|
|
|
|
|
printf ("AIDir %d,%d->%d ", rnr,bnr, 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;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* create a giving number of ai players */
|
|
|
|
|
void
|
|
|
|
|
single_create_ai (int players)
|
|
|
|
@ -457,9 +439,62 @@ single_playergame ()
|
|
|
|
|
for (p = 0; p < MAX_PLAYERS; p++)
|
|
|
|
|
bman.players[p].state = 0;
|
|
|
|
|
|
|
|
|
|
single_create_ai (1);
|
|
|
|
|
single_create_ai (5);
|
|
|
|
|
single_game_new ();
|
|
|
|
|
gfx_game_init ();
|
|
|
|
|
game_loop ();
|
|
|
|
|
gfx_game_shutdown ();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
single_loop ()
|
|
|
|
|
{
|
|
|
|
|
int p;
|
|
|
|
|
_player *pl;
|
|
|
|
|
_point plpos;
|
|
|
|
|
int nearbomb = 0, bestbdir,
|
|
|
|
|
i;
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
printf ("SP: %d,%d NB:", plpos.x, plpos.y); d_bitprint (nearbomb, 5);
|
|
|
|
|
if (nearbomb == 0) { // no bombs found
|
|
|
|
|
bestbdir = ai_findbestbombdir (plpos, pl->d, pl->range);
|
|
|
|
|
if (bestbdir >= 4)
|
|
|
|
|
player_drop_bomb (p);
|
|
|
|
|
else if (bestbdir == -1) {
|
|
|
|
|
pl->d = s_random (4);
|
|
|
|
|
pl->m = 1;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
pl->d = bestbdir;
|
|
|
|
|
pl->m = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// bombs in the near found
|
|
|
|
|
printf (" FB: %d,%d ", plpos.x, plpos.y);
|
|
|
|
|
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 ("D:%d, M:%d, Flee", pl->d, pl->m);
|
|
|
|
|
d_bitprint (i, 4);
|
|
|
|
|
}
|
|
|
|
|
printf ("\n");
|
|
|
|
|
}
|
|
|
|
|
player_ilness_loop (p);
|
|
|
|
|
move_player (p);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|