From e1809dc130280dad76827a48a7ffc39deefc463a Mon Sep 17 00:00:00 2001 From: stpohle Date: Sun, 25 May 2003 02:24:18 +0000 Subject: [PATCH] first try of the AI.. but it's wors they kill themselfs again --- src/player.c | 2 +- src/single.c | 446 +++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 358 insertions(+), 90 deletions(-) diff --git a/src/player.c b/src/player.c index 5015c42..a36b3e2 100644 --- a/src/player.c +++ b/src/player.c @@ -329,7 +329,7 @@ player_drop_bomb (int pl_nr) for (i = 0; ((i < player->bombs_n) && (player->bombs[i].state != BS_off)); i++); - if (i < player->bombs_n) { // free bomb found + if (i < player->bombs_n && PS_IS_alife(player->state)) { // free bomb found // get the best position for the bomb. bomb = &player->bombs[i]; diff --git a/src/single.c b/src/single.c index 59d6767..7ca94c0 100644 --- a/src/single.c +++ b/src/single.c @@ -1,4 +1,4 @@ -/* $Id: single.c,v 1.16 2003/05/23 21:17:30 stpohle Exp $ */ +/* $Id: single.c,v 1.17 2003/05/25 02:24:18 stpohle Exp $ */ /* single player */ #include "basic.h" @@ -29,8 +29,8 @@ single_game_new () bman.players[p].bombs_n = START_BOMBS; bman.players[p].range = START_RANGE; bman.players[p].speed = START_SPEED; - bman.players[p].special= SP_nothing; - bman.updatestatusbar=1; + bman.players[p].special = SP_nothing; + bman.updatestatusbar = 1; for (i = 0; i < MAX_BOMBS; i++) { bman.players[p].bombs[i].state = BS_off; bman.players[p].bombs[i].ex_nr = -1; @@ -43,14 +43,14 @@ single_game_new () bman.players[p].d = 0; } - for (bman.p_nr = -1, p = 0; (bman.p_nr == -1 && p < MAX_PLAYERS); p++) - if (!(PS_IS_used (bman.players[p].state))) - bman.p_nr = p; - - if (bman.p_nr >= MAX_PLAYERS) { - printf ("ERROR in function (single_game_new): couldn't find any free player\n"); - exit (1); - } + for (bman.p_nr = -1, p = 0; (bman.p_nr == -1 && p < MAX_PLAYERS); p++) + if (!(PS_IS_used (bman.players[p].state))) + bman.p_nr = p; + + if (bman.p_nr >= MAX_PLAYERS) { + printf ("ERROR in function (single_game_new): couldn't find any free player\n"); + exit (1); + } bman.players[bman.p_nr].state = PSFM_alife; player_set_gfx (&bman.players[bman.p_nr], 5); @@ -63,100 +63,367 @@ single_game_new () }; +int +ai_checkfield (int x, int y) +{ + return (bman.field[x][y].type == FT_nothing && bman.bfield[x][y] == 0); +} + + +/* 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 ("Check Run away (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) +{ + int d; + int dir = -1; + + for (d = 0; (d < 4 && dir == -1); d++) + if (ai_checkrunaway (p, range, d)) + dir = d; + + d_printf ("ai_runawayfrom (%d)\n", dir); + + return dir; +}; + + +/* count the points for dropping a bomb here */ +int +ai_bombpoints (_point pos, int range) +{ + int points = 0, + d, + r; + _point p, + m; + + if (bman.field[pos.x][pos.y].type != FT_block && bman.field[pos.x][pos.y].type != FT_stone) { + for (d = 0; d < 4; d++) { + switch (d) { + 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; + } + + p = pos; + + for (r = 0; (r < range && bman.field[p.x][p.y].type == FT_nothing); r++) { + p.x += m.x; + p.y += m.y; + } + + if (bman.field[p.x][p.y].type != FT_nothing && bman.field[p.x][p.y].type != FT_block) + points++; + } + } + + if (ai_runawayfrom (pos, range) == -1) + points = 0; + + return points; +}; + + +/* find the best position to go for dropping a bomb */ +int +ai_findbestbombdir (_player * pl) +{ + int points[5] = { 0, 0, 0, 0 }; + int d, + bestd = pl->d; + _point m, + p; + + for (d = 0; d < 5; d++) { + switch (d) { + 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; + case (down): + m.x = 0; + m.y = 1; + break; + default: + m.x = 0; + m.y = 0; + break; + } + + p.x = (pl->pos.x >> 8) + m.x; + p.y = (pl->pos.y >> 8) + m.y; + + points[d] = ai_bombpoints (p, pl->range); + if (points[d] > points[bestd]) + bestd = d; + } + + if (points[bestd] <= points[4] && points[4] != 0) + bestd = 4; + + d_printf ("ai_findbestbombdir (%d %d %d %d %d)\n", points[0], points[1], points[2], points[3], + points[4]); + + return bestd; +} + + /* check if is there is a bom in the near - returns the directions (bits 0(left)-3(down)) where a bomb is */ -int ai_findnearbombs (_player *pl) { - int d, - res = 0, // result if there is a bomb - done = 0, - row; - _point m[4]; // direction addition - _point dist[4][3]; // to check every direction (on three ways) - - for (d = 0; d < 4; d++) + returns the directions (bits 0(left)-3(down) bit4 bomb under us) where a bomb is */ +int +ai_findnearbombs (_player * pl) +{ + int d, + res = 0, // result if there is a bomb + + done = 0, + row; + _point m[4]; // direction addition + _point dist[4]; // to check every direction (on three ways) + + for (d = 0; d < 4; d++) switch (d) { case (left): m[d].x = -1; m[d].y = 0; - dist[d][0].x = (pl->pos.x>>8) - 1; - dist[d][1].x = (pl->pos.x>>8) - 1; - dist[d][2].x = (pl->pos.x>>8) - 1; - dist[d][0].y = (pl->pos.y>>8) - 1; - dist[d][1].y = (pl->pos.y>>8); - dist[d][2].y = (pl->pos.y>>8) + 1; - break; + dist[d].x = (pl->pos.x >> 8) + 1; + dist[d].y = (pl->pos.y >> 8); + break; case (right): m[d].x = 1; m[d].y = 0; - dist[d][0].x = (pl->pos.x>>8) + 1; - dist[d][1].x = (pl->pos.x>>8) + 1; - dist[d][2].x = (pl->pos.x>>8) + 1; - dist[d][0].y = (pl->pos.y>>8) - 1; - dist[d][1].y = (pl->pos.y>>8); - dist[d][2].y = (pl->pos.y>>8) + 1; + dist[d].x = (pl->pos.x >> 8) - 1; + dist[d].y = (pl->pos.y >> 8); break; case (up): m[d].x = 0; m[d].y = -1; - dist[d][0].x = (pl->pos.x>>8) - 1; - dist[d][1].x = (pl->pos.x>>8); - dist[d][2].x = (pl->pos.x>>8) + 1; - dist[d][0].y = (pl->pos.y>>8) - 1; - dist[d][1].y = (pl->pos.y>>8) - 1; - dist[d][2].y = (pl->pos.y>>8) - 1; + dist[d].x = (pl->pos.x >> 8); + dist[d].y = (pl->pos.y >> 8) - 1; break; case (down): m[d].x = 0; m[d].y = 1; - dist[d][0].x = (pl->pos.x>>8) - 1; - dist[d][1].x = (pl->pos.x>>8); - dist[d][2].x = (pl->pos.x>>8) + 1; - dist[d][0].y = (pl->pos.y>>8) + 1; - dist[d][1].y = (pl->pos.y>>8) + 1; - dist[d][2].y = (pl->pos.y>>8) + 1; + dist[d].x = (pl->pos.x >> 8); + dist[d].y = (pl->pos.y >> 8) + 1; break; } - - while (!done) { - done = 1; - - /* check every direction again */ - for (d = 0; d < 4; d++) - for (row = 0; row < 3; row++) - if (dist[d][row].x >= 0 && dist[d][row].x < bman.fieldsize.x && - dist[d][row].y >= 0 && dist[d][row].y < bman.fieldsize.y) { - if (bman.bfield[dist[d][row].x][dist[d][row].y] != 0) { - res |= 1 << d; // set the bit for the direction; - dist[d][row].x = dist[d][row].y = -1; // don't check no more. - } - if (bman.field[dist[d][row].x][dist[d][row].y].type != FT_nothing) - dist[d][row].x = dist[d][row].y = -1; // don't check no more. - if (dist[d][row].x != -1 && dist[d][row].y != -1) { - dist[d][row].x += m[d].x; - dist[d][row].y += m[d].y; - done = 0; - } - } - } - - return res; + + while (!done) { + done = 1; + + /* check every direction again */ + for (d = 0; d < 4; d++) + if (dist[d].x >= 0 && dist[d].x < bman.fieldsize.x && + dist[d].y >= 0 && dist[d].y < bman.fieldsize.y) { + if (bman.bfield[dist[d].x][dist[d].y] != 0) { + res |= 1 << d; // set the bit for the direction; + dist[d].x = dist[d].y = -1; // don't check no more. + } + 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) { + dist[d].x += m[d].x; + dist[d].y += m[d].y; + done = 0; + } + } + } + + if (bman.bfield[pl->pos.x >> 8][pl->pos.y >> 8] != 0) + res |= 16; // set the 4th. bit + + return res; } +/* flee from a bomb in the near */ +int +ai_fleefrombomb (_player * pl, int nearbomb) +{ + int posdir[4]; // possibvle directions to run away + int d = 0, + i, + dir = -1; + _point pos; + + pos.x = pl->pos.x >> 8; + pos.y = pl->pos.y >> 8; + + if (nearbomb == 4) + dir = ai_runawayfrom (pos, pl->range); + + if (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); + + if ((pl->pos.x & 255) != 0 || (pl->pos.y & 255) != 0) + dir = pl->d; + + } + + + return dir; +}; + + void single_loop () { int p; _player *pl; - - for (p = 0; p < MAX_PLAYERS; p++) - if (p != bman.p_nr && PS_IS_playing (bman.players[p].state)) { - pl = &bman.players[p]; - ai_findnearbombs (pl); - player_ilness_loop (p); - } + int nearbomb, + bestbombdir; + + for (p = 0; p < MAX_PLAYERS; p++) + if (p != bman.p_nr && PS_IS_alife (bman.players[p].state)) { + pl = &bman.players[p]; + + bestbombdir = ai_findbestbombdir (pl); + nearbomb = ai_findnearbombs (pl); + + if (((pl->pos.x & 255) >= 64 && (pl->pos.x & 255) <= 255 && pl->d == left) || + ((pl->pos.x & 255) > 0 && (pl->pos.x & 255) <= 192 && pl->d == right) || + ((pl->pos.y & 255) >= 64 && (pl->pos.y & 255) <= 255 && pl->d == up) || + ((pl->pos.y & 255) > 0 && (pl->pos.y & 255) <= 192 && pl->d == down)) { + pl->m = 1; + } + else if (bestbombdir == 4 && nearbomb == 0) // best position is here + player_drop_bomb (p); + else if (nearbomb != 0) { // there is a bomb in the near + pl->m = 1; + pl->d = ai_fleefrombomb (pl, nearbomb); + } + else if (bestbombdir == -1) { // no good position found + pl->d = s_random (4); + pl->m = 1; + } + else { // go into this direction + pl->d = bestbombdir; + pl->m = 1; + } + player_ilness_loop (p); + move_player (p); + } }; + /* create a giving number of ai players */ void single_create_ai (int players) @@ -171,26 +438,27 @@ single_create_ai (int players) if (!(PS_IS_used (bman.players[p].state))) { pl = &bman.players[p]; pl->state |= PSF_used + PSF_alife + PSF_playing; - player_set_gfx (pl, s_random (MAX_PLAYERS)); + player_set_gfx (pl, s_random (MAX_PLAYERS)); } if (pl == NULL) return; } - }; -void single_playergame () { - int p; - - /* delete player from the game */ - for (p = 0; p < MAX_PLAYERS; p++) - bman.players[p].state = 0; +void +single_playergame () +{ + int p; + + /* delete player from the game */ + for (p = 0; p < MAX_PLAYERS; p++) + bman.players[p].state = 0; - single_create_ai (1); - single_game_new (); - gfx_game_init (); + single_create_ai (6); + single_game_new (); + gfx_game_init (); game_loop (); - gfx_game_shutdown (); + gfx_game_shutdown (); };