/* load a random map */ void map_random () { _direntry *destart, *de, *desel; char path[LEN_PATHFILENAME]; int max, sel; sprintf (path, "%s/maps", bman.datapath); desel = destart = s_getdir (path); for (max = 0, de = destart; de != NULL; de = de->next) if ((de->flags & DF_file) == DF_file) max++; sel = s_random (max); for (max = 0, de = destart; max <= sel && de != NULL; de = de->next) if ((de->flags & DF_file) == DF_file) { desel = de; max++; } d_printf ("Random Map %s (%d on %d)\n", desel->name, sel, max); if (desel != NULL) sprintf (map.map, "%s/maps/%s", bman.datapath, desel->name); }
int map_place_player(int pl) { int index; int start_points; int idx; int i; start_points = map_num_defined_start_points(); index = (s_random(MAX_PLAYERS) + 1) % start_points; for (i = 0; i < start_points; i++) { idx = (index + i) % start_points; if ((!map.start_point[idx].used) && (map.start_point[idx].pos.x != -1) && (map.start_point[idx].pos.y != -1)) { players[pl].pos.x = map.start_point[idx].pos.x; players[pl].pos.y = map.start_point[idx].pos.y; map.start_point[idx].used = 1; return 1; } } return 0; }
int map_respawn_player(int pl) { int x; int y; do { x = s_random (map.size.x - 2) + 1; y = s_random (map.size.y - 2) + 1; } while (!map_is_possible_start_point(x, y)); players[pl].pos.x = x; players[pl].pos.y = y; return 1; }
float Distribution::gen() const { if (_type == UNIFORM) { return s_random(_value.uniform.min, _value.uniform.max); } return _value.constant; }
/* 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)); if (bnr != 0) i = bdir[s_random (bnr)]; else i = rdir[s_random (rnr)]; return i; };
void map_genmorerandom () { int x, y, d, ra; /* This is an enhanced version of genrandom() used by "more random" */ d_printf("genmorerandom: *** init ***\n"); /* if we can't load the map check first the fieldsize settings */ if (map.size.x < MIN_FIELDSIZE_X) map.size.x = MIN_FIELDSIZE_X; if (map.size.x > MAX_FIELDSIZE_X) map.size.x = MAX_FIELDSIZE_X; for (x = 0; x < map.size.x; x++) for (y = 0; y < map.size.y; y++) { if ((y == 0) || (y == map.size.y - 1)) map.field[x][y].type = FT_block; else if ((x == 0) || (x == map.size.x - 1)) map.field[x][y].type = FT_block; else { // create random field ra = s_random (256) & 3; d_printf("genmorerandom: ra = %i\n", ra); if (ra == 0) map.field[x][y].type = FT_nothing; else if (ra == 1) map.field[x][y].type = FT_block; else map.field[x][y].type = FT_stone; } for (d = 0; d < 4; d++) map.field[x][y].ex[d].frame = map.field[x][y].ex[d].count = 0; map.field[x][y].ex_nr = -1; map.field[x][y].frame = 0.0f; map.field[x][y].special = FT_nothing; } d_printf("genmorerandom: *** exit ***\n"); /* set the corners of the map to be valid start points */ // map_ensure_corner_start_points(); }
/* create a giving number of ai players */ int single_create_ai (int num_players) { int p, count, try, gfx_sel, i = 0; _player *pl = NULL; for (count = 0; count < num_players; count++) { /* find free players */ for (pl = NULL, p = 0; (pl == NULL && p < MAX_PLAYERS);p++) if (p < MAX_PLAYERS && !(PS_IS_used (players[p].state))) { pl = &players[p]; sprintf (pl->name, "AI %d", p + 1); pl->state |= PSF_used + PSF_alife + PSF_playing + PSF_ai; pl->net.flags = NETF_firewall; sprintf (pl->net.addr.host, "localhost"); sprintf (pl->net.addr.port, "11000"); try = 0; do { gfx_sel = s_random (gfx.player_gfx_count); MW_IS_GFX_SELECT (gfx_sel, i); try++; } while (try < 100 && i != -1); pl->wins = 0; pl->points = 0; pl->team_nr = -1; player_set_gfx (pl, gfx_sel); team_choose (pl); } if (pl == NULL) { d_printf ("single_create_ai: No free Player found.\n"); return -1; } else d_printf ("single_create_ai: Player %d Created Name:%s\n", pl - players, pl->name); } if (pl != NULL) return pl - players; return -1; };
void map_genrandom () { int x, y, d; /* if we can't load the map check first the fieldsize settings */ if (map.size.x < MIN_FIELDSIZE_X) map.size.x = MIN_FIELDSIZE_X; if (map.size.x > MAX_FIELDSIZE_X) map.size.x = MAX_FIELDSIZE_X; for (x = 0; x < map.size.x; x++) for (y = 0; y < map.size.y; y++) { if ((y == 0) || (y == map.size.y - 1)) map.field[x][y].type = FT_block; else if ((x == 0) || (x == map.size.x - 1)) map.field[x][y].type = FT_block; else if (((x & 1) == 0) && ((y & 1) == 0)) map.field[x][y].type = FT_block; else { // create random field if ((s_random (256) & 3) == 0) map.field[x][y].type = FT_nothing; else map.field[x][y].type = FT_stone; } for (d = 0; d < 4; d++) map.field[x][y].ex[d].frame = map.field[x][y].ex[d].count = 0; map.field[x][y].ex_nr = -1; map.field[x][y].frame = 0.0f; map.field[x][y].special = FT_nothing; } /* set the corners of the map to be valid start points */ // map_ensure_corner_start_points(); }
int map_create_and_add_start_point(int tol) { int x; int y; int dx; int dy; int init_x; int init_y; int end_x; int end_y; int step_x; int step_y; /* this changes how we traverse the map when looking for a place to put * a start point. this is so all the start points don't get stuck in one * part of the map if the map is large enough */ if (s_random(100) % 2) { init_x = 0; end_x = map.size.x; step_x = 1; } else { init_x = map.size.x - 1; end_x = -1; step_x = -1; } if (s_random(100) % 2) { init_y = 0; end_y = map.size.y; step_y = 1; } else { init_y = map.size.y - 1; end_y = -1; step_y = -1; } /* first try only FT_nothing fields as start points */ for (x = init_x; x != end_x; x += step_x) { for (y = init_y; y != end_y; y+= step_y) { if ((map.field[x][y].type == FT_nothing) && (map_check_start_point(x, y, tol))) { dx = (x >= map.size.x - 2) ? -1:1; dy = (y >= map.size.y - 2) ? -1:1; if ((map_is_removable_field(x+dx, y)) && (map_is_removable_field(x, y+dy))) { /* printf("Creating Start Point (%d, %d).\n", x, y); */ map.field[x][y].type = FT_nothing; map.field[x+dx][y].type = FT_nothing; map.field[x][y+dy].type = FT_nothing; map_add_start_point(x, y); return 1; } } } } /* if we get here we didn't find a useful FT_nothing field, so check the FT_stone * fields */ for (x = init_x; x != end_x; x += step_x) { for (y = init_y; y != end_y; y+= step_y) { if ((map.field[x][y].type == FT_stone) && (map_check_start_point(x, y, tol))) { dx = (x >= map.size.x - 2) ? -1:1; dy = (y >= map.size.y - 2) ? -1:1; if ((map_is_removable_field(x+dx, y)) && (map_is_removable_field(x, y+dy))) { /* printf("Creating Start Point (%d, %d).\n", x, y); */ map.field[x][y].type = FT_nothing; map.field[x+dx][y].type = FT_nothing; map.field[x][y+dy].type = FT_nothing; map_add_start_point(x, y); return 1; } } } } /* if we get to this point, we tried every field that we want to turn into a * start point, so we return 0 indicating failure */ return 0; }
// loads or generate an map void map_new (char *filename) { int x, y; FILE *fmap; signed char old_maptype = map.type; int pl_cnt, pl; /* initialize the start_point array in the _map struct */ map_init_start_points(); if (filename) { fmap = fopen (filename, "r"); /* if we can't open the given filename for any reason, reverting to default value else, load the file map */ if (fmap) map_load (fmap); } else fmap = NULL; // Clean and create the field // if (fmap == NULL) map_genrandom (); /* Generate a More random map if requested */ if (map.map_selection == MAPS_morerand) map_genmorerandom(); if (map.type == -1) map.type = s_random (MAPT_max); if (map.type == MAPT_tunnel) { /* insert tunnels */ for (x = 0; x < GAME_MAX_TUNNELS; x++) map.tunnel[x].x = map.tunnel[x].y = -1; map.field[3][3].type = FT_tunnel; map.field[3][3].special = 0; map.field[map.size.x - 4][map.size.y - 4].type = FT_tunnel; map.field[map.size.x - 4][map.size.y - 4].special = 1; if (map.size.y > 12) { map.field[map.size.x - 4][3].type = FT_tunnel; map.field[map.size.x - 4][3].special = 2; map.field[3][map.size.y - 4].type = FT_tunnel; map.field[3][map.size.y - 4].special = 3; map.tunnel[0].x = map.size.x - 4; map.tunnel[0].y = 3; map.tunnel[1].x = 3; map.tunnel[1].y = map.size.y - 4; map.tunnel[2].x = map.size.x - 4; map.tunnel[2].y = map.size.y - 4; map.tunnel[3].x = 3; map.tunnel[3].y = 3; } else { map.tunnel[0].x = map.size.x - 4; map.tunnel[0].y = map.size.y - 4; map.tunnel[1].x = 3; map.tunnel[1].y = 3; } } /* delete the bfield data */ for (x = 0; x < MAX_FIELDSIZE_X; x++) for (y = 0; y < MAX_FIELDSIZE_Y; y++) map.bfield[x][y] = 0; /* count the number of players on this map so we know how many starting points * to find */ pl_cnt = 0; for (pl = 0; pl < MAX_PLAYERS; pl++) { if (PS_IS_used (players[pl].state)) { pl_cnt++; } } /* identify possible starting positions for players and store them in the * start_point array in the _map struct. This will always succeed. If * it cannot find starting points within the tolerance, it first attempts * to create start points within the tolerence and otherwise lowers the * tolerence until it can satisfy the proper number of start points. * eventually the tolerence reaches 0, so it can, in the worst case, start * all players at the same start point. */ map_find_and_add_start_points(pl_cnt - map_num_defined_start_points(), MAP_POSITION_TOLERENCE); /* Set the Playerinformation */ map_set_playerposition (fmap != NULL); /* put the fire powerups in the field */ map_fillitems (FT_fire, map.fire); /* put the bomb powerups in the field */ map_fillitems (FT_bomb, map.bombs); /* put the shoe powerup in the field */ map_fillitems (FT_shoe, map.shoes); /* put the death ?powerups? in the field */ map_fillitems (FT_death, map.death); /* put the mixed powerrup in the field */ map_fillitems (FT_mixed, map.mixed); /* put the trigger special in the field */ map_fillitems (FT_sp_trigger, map.sp_trigger); /* put the row special in the field */ map_fillitems (FT_sp_row, map.sp_row); /* put the push special in the field */ map_fillitems (FT_sp_push, map.sp_push); map_fillitems (FT_sp_liquid, map.sp_push); map_fillitems (FT_sp_moved, map.sp_push); /* put the push special in the field */ map_fillitems(FT_sp_kick,map.sp_kick); map.type = old_maptype; }
/* single player loop for calculating the ai players */ void single_loop () { int p; _player *pl; _point plpos; int nearbomb = 0, bestbdir, i; _airunaway rawdir; if (GT_MP_PTPS) // we are not the master so no need for this. return; for (p = 0; p < MAX_PLAYERS; p++) if (p != bman.p_nr && PS_IS_aiplayer (players[p].state)) { if (PS_IS_alife (players[p].state)) { pl = &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 & DIRM_under) { if (ai_easyrunaway (plpos, pl->range) != 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 rawdir = ai_runawayfrom (plpos, nearbomb, pl->range, 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; } else if (rawdir.bestdir == -1 && rawdir.dir == 0) { /* no good ways found, just run in the opposite direction of the bomb */ if (map.field[(int) pl->pos.x][(int) pl->pos.y].type == FT_nothing || map.field[(int) pl->pos.x][(int) pl->pos.y].type >= FT_tunnel) pl->m = 1; } } if (pl->m == 0 && map.field[(int) pl->pos.x][(int) pl->pos.y].type == FT_tunnel) pl->m = 1; } player_ilness_loop (p); player_move (p); } else player_checkdeath (p); } };
/* give the run away direction the return value: */ _airunaway ai_runawayfrom (_point p, int nearbomb, int range, signed char norecursive) { int i, done = 0, nbomb, tdir, _i, bdirpoints = 10, j, c, dist = 0; _airunaway res; _point pos[4], tpos; res.dir = 0; res.bestdir = -1; for (i = 0; i < 4; i++) { pos[i] = p; pos[i].x += dir_change[i].x; pos[i].y += dir_change[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); } /* test the possible ways */ while (!done) { done = 1; dist++; 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 >= map.size.x - 1 || pos[i].y >= map.size.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 + dir_change[j].x; tpos.y = pos[i].y + dir_change[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, range, 1).dir; _i = ai_invertdir (i); if (tdir != (1 << _i)) { // usefull direction res.dir |= (1 << i); // add this one } else { c = -1; } } else res.dir |= (1 << i); /* check for the best direction */ 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 += dir_change[i].x; pos[i].y += dir_change[i].y; if (dist > range && res.bestdir == -1) { res.dir |= (1 << i); res.bestdir = i; } } } } } return res; };