From 03ecc242d655cf7a589f49316f11879862079732 Mon Sep 17 00:00:00 2001 From: stpohle Date: Wed, 28 May 2003 22:31:46 +0000 Subject: [PATCH] single player ai test 2 --- ChangeLog | 3 + src/basic.h | 9 ++ src/bomberclone.h | 12 +- src/debug.c | 13 ++ src/single.c | 357 +++++++++++++++++++++++++--------------------- 5 files changed, 232 insertions(+), 162 deletions(-) diff --git a/ChangeLog b/ChangeLog index 95b8804..04ccd43 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +- Added Sound Support (thanks to Henrik Enqvist for + the help and the sound files.) + - Added new powerups (Patty) - Fixed make install, so the source will be able to diff --git a/src/basic.h b/src/basic.h index c40a352..ddb5746 100644 --- a/src/basic.h +++ b/src/basic.h @@ -161,6 +161,15 @@ enum _direction { // to handle directions better down }; +enum _dirbitmask { // bit mask for the directions + DIRM_left = 1, + DIRM_right = 2, + DIRM_up = 4, + DIRM_down = 8, + DIRM_under = 16 +}; + + struct __point { short int x; short int y; diff --git a/src/bomberclone.h b/src/bomberclone.h index 3a103e6..64b260c 100644 --- a/src/bomberclone.h +++ b/src/bomberclone.h @@ -1,4 +1,4 @@ -/* $Id: bomberclone.h,v 1.26 2003/05/26 20:25:54 stpohle Exp $ */ +/* $Id: bomberclone.h,v 1.27 2003/05/28 22:31:47 stpohle Exp $ */ /* bomberclone.h */ #ifndef _BOMBERCLONE_H_ @@ -235,6 +235,7 @@ extern void d_in_pl_detail (char *head); extern void d_playerdetail (char *head); extern void d_gamedetail (char *head); extern void d_printf (char *fmt,...); +extern void d_bitprint (int bits, int nr); // single.c @@ -242,6 +243,15 @@ extern void single_game_new (); extern void single_create_ai (int players); extern void single_loop(); extern void single_playergame (); +extern int ai_choosedir (int dir, int nearbomb, int oldpos); +extern int ai_invertdir (int dir); +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 int ai_checkfield (int x, int y); + // mapmenu.c extern void map_random (); diff --git a/src/debug.c b/src/debug.c index 379462c..e227867 100644 --- a/src/debug.c +++ b/src/debug.c @@ -37,3 +37,16 @@ void d_playerdetail (char *head) { for (i = 0; i < MAX_PLAYERS; i++) d_printf ("%2d %16s %3d %3d %3d %3d [%s:%s]\n",i, bman.players[i].name, bman.players[i].gfx_nr, bman.players[i].state, bman.players[i].points, bman.players[i].wins, bman.players[i].net.addr.host, bman.players[i].net.addr.port); }; + + +void d_bitprint (int bits, int nr) { + int i; + + for (i = nr-1; i >= 0; i--) + if ((bits & (1 << i)) == 0) + printf ("-"); + else + printf ("X"); + printf (" "); +}; + diff --git a/src/single.c b/src/single.c index 72b1c5b..5997d46 100644 --- a/src/single.c +++ b/src/single.c @@ -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,71 +70,96 @@ ai_checkfield (int x, int y) } -/* check if we can run away in this direction */ -int -ai_checkrunaway (_point pos, int range, int direction) -{ - _point m, - p; - int ok = 0, - i; - - p = pos; - - switch (direction) { - case (left): - m.x = -1; - m.y = 0; - break; - case (right): - m.x = 1; - m.y = 0; - break; - case (up): - m.x = 0; - m.y = -1; - break; - default: - m.x = 0; - m.y = 1; - break; - } - - 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; - } - else { - if (ai_checkfield (p.x + 1, p.y) || ai_checkfield (p.x - 1, p.y)) - ok = 1; - } - } - - if (i >= range) - ok = 1; - - d_printf ("ai_runaway (pos %d,%d , direction %d) %d\n", pos.x, pos.y, direction, ok); - - return ok; -}; - - /* give the run away direction */ int -ai_runawayfrom (_point p, int range) +ai_runawayfrom (_point p, int nearbomb, signed char norecursive) { - int d; - int dir = -1; - - for (d = 0; (d < 4 && dir == -1); d++) - if (ai_checkrunaway (p, range, d)) - dir = d; - - return dir; + int i, done = 0, dir = 0, nbomb, tdir, _i; + _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; + } + 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; + } + } + } + } + + printf ("["); d_bitprint (dir, 4); + + 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)); + } + } + + d_bitprint (dir, 4); printf ("] "); + + return dir; }; @@ -181,9 +206,9 @@ 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); +/* random choose direction */ +int +ai_choosedir (int dir, int nearbomb, int oldpos) { + int rdir[4]; + int bdir[4]; + 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)]; + + printf ("AIDir %d,%d->%d ", rnr,bnr, i); + + return i; +}; - d_printf ("single_loop pos:%d,%d nearbomb:%d bestbombdir:%d, checkpos: %d\n", plpos.x, - plpos.y, nearbomb, bestbombdir, i); - if (!i) { - /* we're still moving */ - pl->m = 1; - } - else { - nearbomb = ai_findnearbombs (plpos); - if (nearbomb == 0) { // no bombs found - } - else { - // bombs in the near found - pl->m = 1; - pl->d = ai_fleefrombomb (plpos, nearbomb, pl->range + 1); - printf (" %d ", pl->d); - } - } - player_ilness_loop (p); - move_player (p); - } +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); + } +};