/* Map Randomizer * Glenn Rice */ #include #include #include #include enum { BOARD = 0, SEA, DESERT, FOREST, HILL, MOUNTAIN, PLAIN, FIELD, GOLD }; enum { NO_PORT = 0, TIMBER_PORT, BRICK_PORT, GRAIN_PORT, ORE_PORT, WOOL_PORT, MULTI_PORT }; enum { PORT_ORIENTATION_E = 0, PORT_ORIENTATION_NE, PORT_ORIENTATION_NW, PORT_ORIENTATION_W, PORT_ORIENTATION_SW, PORT_ORIENTATION_SE, }; typedef struct _coords { int chit_loc; int x; int y; } Coords; typedef struct _tile { int tile_type; int chit_num; int port_type; int port_pos; int is_rand; int is_high; } Tile; typedef struct _mapRow { int row_len; Tile *tiles; } MapRow; typedef struct _map { int num_rows; int num_land; int num_rand_des; int num_des; int num_rand; int num_port; int num_sea; int num_rand_sea; MapRow *rows; } Map; typedef struct _possPort { Tile *loc; int i; int j; int num_orients; int orients[6]; } PossPort; /* Prototypes */ void process_args (int argc, char *argv[]); void print_usage_menu (); char* get_title (FILE *fi); char* get_game_opts (FILE *fi); int* get_chits (int *num_chits, FILE *fi); Map get_map (FILE *fi); char * get_extras (FILE *fi); void randomize_land (Map map); void place_ports (Map map); int land_has_port (Map map, int i, int j); void randomize_ports (Map map); void find_next_chit_num (Map map, int *x, int *y, int k); int* randomize_chits (Map map, int *chits, int *num_chits); int find_allowable_position (Map map, Coords *chit_hex, int k); int move_high_odds_to_end (int *chits, int num_chits); int high_is_adj (Map map, int i, int j); void write_chits (int *chits, int num_chits, FILE *fo); void write_map (Map map, FILE *fo); /* Parameters & Default Values */ char *in_file = NULL; // Filename to read game information from char *out_file = NULL; // Filename to write game to int randomization_opts = 7; // int randomize_sea = 0; // If set to 1 then sea is randomized with land int main (int argc, char *argv[]) { char *title; char *game_opts; int *chits; int num_chits; Map map; char *extras; FILE *fi = NULL; FILE *fo = stdout; process_args(argc, argv); // Read information from the game file fi = fopen(in_file, "r"); if (fi == NULL) { fprintf(stderr, "FATAL: Error openning file %s\n", in_file); exit(1); } title = get_title (fi); game_opts = get_game_opts (fi); chits = get_chits (&num_chits, fi); map = get_map (fi); extras = get_extras (fi); fclose (fi); // Randomize the various aspects of the map if (randomization_opts & 2) randomize_land (map); if (randomization_opts & 5) randomize_ports (map); if (randomization_opts & 1) chits = randomize_chits (map, chits, &num_chits); // Write the new game file if (out_file != NULL) fo = fopen (out_file, "w"); if (fo == NULL) { fprintf (stderr, "FATAL: Unable to write to file %s\n", out_file); exit(1); } fprintf (fo, "%s\n", title); fprintf (fo, "%s", game_opts); write_chits (chits, num_chits, fo); write_map (map, fo); fprintf (fo, "%s\n", extras); fclose (fo); // Free the variables that were allocated free (title); free (game_opts); int i; for (i = 0; i < map.num_rows; i++) free (map.rows[i].tiles); free (map.rows); free (chits); } void process_args(int argc, char *argv[]) { int i=1; while (i < argc) { switch(argv[i][0]) { case '-': switch(argv[i][1]) { case 'h': print_usage_menu(); exit(0); break; case 'o': out_file = argv[++i]; i++; break; case 'p': randomization_opts = randomization_opts ^ 4; i++; break; case 'l': randomization_opts = randomization_opts ^ 2; i++; break; case 'c': randomization_opts = randomization_opts ^ 1; i++; break; case 's': randomize_sea = 1; i++; break; default: fprintf(stderr, "Unknown argument %s\n\n", argv[i]); print_usage_menu(); exit(1); } break; default: in_file = argv[i]; i++; break; } } } void print_usage_menu() { fprintf(stderr, "Pioneers Map Randomizer Usage:\n"); fprintf(stderr, "map-randomizer [OPTIONS] input-file\n\n"); fprintf(stderr, "input-file is a pioneers .game file to read the game information from\n\n"); fprintf(stderr, " Options : Description\n"); fprintf(stderr, " -h : Prints this message\n"); fprintf(stderr, " -o file : File to store game in (default is stderr)\n"); fprintf(stderr, " -p : Don't randomize ports\n"); fprintf(stderr, " -l : Don't randomize land\n"); fprintf(stderr, " -c : Don't randomize chits\n"); fprintf(stderr, " -s : Randomize sea tiles with land (ignored if the -l parameter is also used)\n"); fprintf(stderr, "\n"); } char* get_title (FILE *fi) { char title[100]; char *new_title; while ((!feof (fi)) && (strncmp (title, "title", 5) != 0)) { fgets (title, sizeof (title), fi); } strtok (title, "\n"); new_title = (char *) malloc (sizeof(char)*(strlen(title) + 23)); return strcpy (new_title, strcat (title, " Randomized")); } char* get_game_opts (FILE *fi) { char game_opts_line[100]; char *game_opts; char *temp_game_opts; fpos_t position; fgets (game_opts_line, sizeof (game_opts_line), fi); game_opts = (char *) malloc (sizeof(char)); strcpy (game_opts, "\0"); do { if (strncmp (game_opts_line, "random", 6) == 0) fgets (game_opts_line, sizeof (game_opts_line), fi); temp_game_opts = (char *) malloc (sizeof(char)*(strlen(game_opts_line)+strlen(game_opts)+1)); strcpy(temp_game_opts, game_opts); strcat (temp_game_opts, game_opts_line); free (game_opts); game_opts = temp_game_opts; fgetpos (fi, &position); fgets (game_opts_line, sizeof (game_opts_line), fi); } while ((!feof (fi)) && (strncmp (game_opts_line, "chits", 5) != 0)); fsetpos (fi, &position); return game_opts; } int* get_chits (int *num_chits, FILE *fi) { int i; char chit_string[1000]; char *pos; int tmp_num_chits = 0; int *chits; while ((!feof (fi)) && (strncmp (chit_string, "chits", 5) != 0)) { fgets (chit_string, sizeof (chit_string), fi); } if (strncmp (chit_string, "chits", 5) != 0) { fprintf(stderr, "FATAL: Invalid game file %s - chits not defined in file\n", in_file); exit(1); } pos = chit_string; while (pos != NULL) { pos = strchr (pos+1, ','); tmp_num_chits++; } pos = chit_string + 6; chits = (int *) malloc (sizeof (int) * tmp_num_chits); for (i = 0; i < tmp_num_chits; i++) { chits[i] = atoi (pos); pos = strchr (pos, ',') + 1; } if (!chits[tmp_num_chits - 1]) tmp_num_chits--; *num_chits = tmp_num_chits; return chits; } Map get_map (FILE *fi) { fpos_t position; char map_line[150]; int num_rows = 0; Map map; while ((!feof (fi)) && (strncmp (map_line, "map", 3) != 0)) { fgets (map_line, sizeof (map_line), fi); } if (strncmp (map_line, "map", 3) != 0) { fprintf(stderr, "FATAL: Invalid game file %s - map not found in file\n", in_file); exit(1); } // Count the number of rows in the map fgetpos (fi, &position); while ((map_line[0] != '.') && (!feof (fi))) { fgets (map_line, sizeof (map_line), fi); num_rows++; } num_rows--; if (map_line[0] != '.') { fprintf (stderr, "FATAL: Invalid game file %s - map not terminated\n", in_file); exit(1); } fsetpos (fi, &position); map.num_rows = num_rows; map.num_land = 0; map.num_rand = 0; map.num_rand_des = 0; map.num_des = 0; map.num_port = 0; map.num_rand_sea = 0; map.num_sea = 0; map.rows = (MapRow *) malloc (sizeof (MapRow) * num_rows); int i; for (i = 0; i < num_rows; i++) { // Count the number of tiles in this row fgetpos (fi, &position); int c = '\0'; int row_len = 1; while (c != '\n') { c = fgetc (fi); if (c == ',') row_len++; } fsetpos (fi, &position); map.rows[i].row_len = row_len; map.rows[i].tiles = (Tile *) malloc (sizeof (Tile) * row_len); c = '\0'; int j; for (j = 0; j < row_len; j++) { map.rows[i].tiles[j].is_high = 0; do c = fgetc (fi); while (c == ' '); switch (c) { case '-': case '\n': map.rows[i].tiles[j].tile_type = BOARD; break; case 's': map.rows[i].tiles[j].tile_type = SEA; break; case 'd': map.rows[i].tiles[j].tile_type = DESERT; map.num_rand_des++; map.num_des++; break; case 't': map.rows[i].tiles[j].tile_type = FOREST; break; case 'h': map.rows[i].tiles[j].tile_type = HILL; break; case 'm': map.rows[i].tiles[j].tile_type = MOUNTAIN; break; case 'p': map.rows[i].tiles[j].tile_type = PLAIN; break; case 'f': map.rows[i].tiles[j].tile_type = FIELD; break; case 'g': map.rows[i].tiles[j].tile_type = GOLD; break; default: fprintf (stderr, "FATAL: Invalid game file %s - unknown tile type at (%d, %d)\n", in_file, i, j); exit(1); break; } if (c != '\n') do c = fgetc (fi); while (c == ' '); switch (map.rows[i].tiles[j].tile_type) { case BOARD: map.rows[i].tiles[j].port_type = NO_PORT; map.rows[i].tiles[j].chit_num = -1; map.rows[i].tiles[j].is_rand = 0; break; case SEA: map.num_sea++; map.rows[i].tiles[j].chit_num = -1; if ((c != ',') && (c != '\n') && (c != '+')) { switch (c) { case 'l': map.rows[i].tiles[j].port_type = TIMBER_PORT; break; case 'b': map.rows[i].tiles[j].port_type = BRICK_PORT; break; case 'g': map.rows[i].tiles[j].port_type = GRAIN_PORT; break; case 'o': map.rows[i].tiles[j].port_type = ORE_PORT; break; case 'w': map.rows[i].tiles[j].port_type = WOOL_PORT; break; case '?': map.rows[i].tiles[j].port_type = MULTI_PORT; break; } do c = fgetc (fi); while (c == ' '); if (((c - 48) < 0) || ((c - 48) > 9)) map.rows[i].tiles[j].port_pos = 0; else map.rows[i].tiles[j].port_pos = c - 48; map.num_port++; if (c != '+') do c = fgetc (fi); while (c == ' '); } else { map.rows[i].tiles[j].port_type = NO_PORT; map.rows[i].tiles[j].port_pos = -1; } if (c == '+') { map.rows[i].tiles[j].is_rand = 0; do c = fgetc (fi); while (c == ' '); } else { map.rows[i].tiles[j].is_rand = randomize_sea; map.num_rand_sea++; } break; default: map.rows[i].tiles[j].port_type = NO_PORT; map.rows[i].tiles[j].port_pos = -1; map.rows[i].tiles[j].chit_num = c - 48; do c = fgetc (fi); while (c == ' '); while ((c != ',') && (c != '\n') && (c != '+')) { map.rows[i].tiles[j].chit_num = (map.rows[i].tiles[j].chit_num * 10) + (c - 48); do c = fgetc (fi); while (c == ' '); } if (c == '+') { do c = fgetc (fi); while (c == ' '); map.rows[i].tiles[j].is_rand = 0; if (map.rows[i].tiles[j].tile_type == DESERT) map.num_rand_des--; } else { map.rows[i].tiles[j].is_rand = 1; map.num_rand++; } map.num_land++; break; } } } return map; } char * get_extras (FILE *fi) { char extras_line[100]; char *extras; char *temp_extras; while ((!feof (fi)) && (extras_line[0] != '.')) fgets (extras_line, sizeof (extras_line), fi); fgets (extras_line, sizeof (extras_line), fi); extras = (char *) malloc (sizeof(char)); extras[0] = '\0'; if (!feof (fi)) { do { temp_extras = (char *) malloc (sizeof(char)*(strlen(extras_line)+strlen(extras)+1)); strcpy(temp_extras, extras); strcat (temp_extras, extras_line); free (extras); extras = temp_extras; fgets (extras_line, sizeof (extras_line), fi); } while (!feof (fi)); } return extras; } void randomize_land (Map map) { int seed = time(NULL); int total_rand; int i; int j; Tile **rand_land; int k = 0; int rand_pos; Tile tmp_tile; srand(seed); if (randomize_sea) total_rand = map.num_rand + map.num_rand_sea; else total_rand = map.num_rand; rand_land = (Tile **) malloc (sizeof(Tile *)*(total_rand)); for (i = 0; i < map.num_rows; i++) for (j = 0; j < map.rows[i].row_len; j++) if (map.rows[i].tiles[j].is_rand) { rand_land[k] = &map.rows[i].tiles[j]; k++; } for (i = 0; i < total_rand; i++) { rand_pos = (rand () % total_rand - i) + i; tmp_tile.tile_type = rand_land[i]->tile_type; rand_land[i]->tile_type = rand_land[rand_pos]->tile_type; rand_land[rand_pos]->tile_type = tmp_tile.tile_type; tmp_tile.chit_num = rand_land[i]->chit_num; rand_land[i]->chit_num = rand_land[rand_pos]->chit_num; rand_land[rand_pos]->chit_num = tmp_tile.chit_num; tmp_tile.port_type = rand_land[i]->port_type; rand_land[i]->port_type = rand_land[rand_pos]->port_type; rand_land[rand_pos]->port_type = tmp_tile.port_type; tmp_tile.port_pos = rand_land[i]->port_pos; rand_land[i]->port_pos = rand_land[rand_pos]->port_pos; rand_land[rand_pos]->port_pos = tmp_tile.port_pos; tmp_tile.is_rand = rand_land[i]->is_rand; rand_land[i]->is_rand = rand_land[rand_pos]->is_rand; rand_land[rand_pos]->is_rand = tmp_tile.is_rand; } free (rand_land); if (randomize_sea) place_ports (map); } void place_ports (Map map) { int seed = time(NULL); int i; int j; int *orig_ports; int l = 0; PossPort **poss_ports; int k = 0; int rand_pos; int rand_orient; srand(seed); // First analyze the map and find the original ports and the possible places where ports may be placed. orig_ports = (int *) malloc (sizeof(int)*map.num_port); poss_ports = (PossPort **) malloc (sizeof(PossPort *)*map.num_sea); for (i = 0; i < map.num_rows; i++) for (j = 0; j < map.rows[i].row_len; j++) { if (map.rows[i].tiles[j].tile_type == SEA) { poss_ports[k] = (PossPort *) malloc (sizeof(PossPort)); if (map.rows[i].tiles[j].port_type) { orig_ports[l] = map.rows[i].tiles[j].port_type; map.rows[i].tiles[j].port_type = NO_PORT; map.rows[i].tiles[j].port_pos = -1; l++; } poss_ports[k]->orients[0] = (j < map.rows[i].row_len - 1 && map.rows[i].tiles[j+1].tile_type > 2); poss_ports[k]->orients[1] = (i > 0 && ((i%2 == 0 && j < map.rows[i-1].row_len && map.rows[i-1].tiles[j].tile_type > 2) || (i%2 == 1 && j < map.rows[i-1].row_len - 1 && map.rows[i-1].tiles[j+1].tile_type > 2))); poss_ports[k]->orients[2] = (i > 0 && ((i%2 == 0 && j > 0 && j < map.rows[i-1].row_len + 1 && map.rows[i-1].tiles[j-1].tile_type > 2) || (i%2 == 1 && j < map.rows[i-1].row_len && map.rows[i-1].tiles[j].tile_type > 2))); poss_ports[k]->orients[3] = (j > 0 && map.rows[i].tiles[j-1].tile_type > 2); poss_ports[k]->orients[4] = (i < map.num_rows - 1 && ((i%2 == 0 && j > 0 && j < map.rows[i+1].row_len + 1 && map.rows[i+1].tiles[j-1].tile_type > 2) || (i%2 == 1 && j < map.rows[i+1].row_len && map.rows[i+1].tiles[j].tile_type > 2))); poss_ports[k]->orients[5] = (i < map.num_rows - 1 && ((i%2 == 0 && j < map.rows[i+1].row_len && map.rows[i+1].tiles[j].tile_type > 2) || (i%2 == 1 && j < map.rows[i+1].row_len - 1 && map.rows[i+1].tiles[j+1].tile_type > 2))); poss_ports[k]->num_orients = 0; int h; for (h = 0; h < 6; h++) poss_ports[k]->num_orients += poss_ports[k]->orients[h]; if (poss_ports[k]->num_orients) { poss_ports[k]->loc = &map.rows[i].tiles[j]; poss_ports[k]->i = i; poss_ports[k]->j = j; k++; } else free (poss_ports[k]); } } for (i = 0; i < map.num_port; i++) { int found = 0; while (!found) { if (k <= 0) { fprintf (stderr, "FATAL: Arrived at an impossible situation - could not prevent bad ports\n"); exit(1); } rand_pos = rand () % k; if (poss_ports[rand_pos]->orients[0] && land_has_port (map, poss_ports[rand_pos]->i, poss_ports[rand_pos]->j+1)) { poss_ports[rand_pos]->orients[0] = 0; poss_ports[rand_pos]->num_orients--; } if (poss_ports[rand_pos]->orients[1] && ((poss_ports[rand_pos]->i%2 == 0 && land_has_port (map, poss_ports[rand_pos]->i-1, poss_ports[rand_pos]->j)) || (poss_ports[rand_pos]->i%2 == 1 && land_has_port (map, poss_ports[rand_pos]->i-1, poss_ports[rand_pos]->j+1)))) { poss_ports[rand_pos]->orients[1] = 0; poss_ports[rand_pos]->num_orients--; } if (poss_ports[rand_pos]->orients[2] && ((poss_ports[rand_pos]->i%2 == 0 && land_has_port (map, poss_ports[rand_pos]->i-1, poss_ports[rand_pos]->j-1)) || (poss_ports[rand_pos]->i%2 == 1 && land_has_port (map, poss_ports[rand_pos]->i-1, poss_ports[rand_pos]->j)))) { poss_ports[rand_pos]->orients[2] = 0; poss_ports[rand_pos]->num_orients--; } if (poss_ports[rand_pos]->orients[3] && land_has_port (map, poss_ports[rand_pos]->i, poss_ports[rand_pos]->j-1)) { poss_ports[rand_pos]->orients[3] = 0; poss_ports[rand_pos]->num_orients--; } if (poss_ports[rand_pos]->orients[4] && ((poss_ports[rand_pos]->i%2 == 0 && land_has_port (map, poss_ports[rand_pos]->i+1, poss_ports[rand_pos]->j-1)) || (poss_ports[rand_pos]->i%2 == 1 && land_has_port (map, poss_ports[rand_pos]->i+1, poss_ports[rand_pos]->j)))) { poss_ports[rand_pos]->orients[4] = 0; poss_ports[rand_pos]->num_orients--; } if (poss_ports[rand_pos]->orients[5] && ((poss_ports[rand_pos]->i%2 == 0 && land_has_port (map, poss_ports[rand_pos]->i+1, poss_ports[rand_pos]->j)) || (poss_ports[rand_pos]->i%2 == 1 && land_has_port (map, poss_ports[rand_pos]->i+1, poss_ports[rand_pos]->j+1)))) { poss_ports[rand_pos]->orients[5] = 0; poss_ports[rand_pos]->num_orients--; } if (poss_ports[rand_pos]->num_orients <= 0) { free (poss_ports[rand_pos]); for (j = rand_pos; j < k - 1; j++) { poss_ports[j] = poss_ports[j+1]; } k--; } else found = 1; } poss_ports[rand_pos]->loc->port_type = orig_ports[i]; rand_orient = rand () % poss_ports[rand_pos]->num_orients; l = 0; while (!poss_ports[rand_pos]->orients[l]) l++; for (j = 0; j < rand_orient; j++) { l++; while (!poss_ports[rand_pos]->orients[l]) l++; } poss_ports[rand_pos]->loc->port_pos = l; free (poss_ports[rand_pos]); for (j = rand_pos; j < k - 1; j++) { poss_ports[j] = poss_ports[j+1]; } k--; } for (i = 0; i < k; i++) free (poss_ports[i]); free (orig_ports); free (poss_ports); } int land_has_port (Map map, int i, int j) { return (j < map.rows[i].row_len - 1 && map.rows[i].tiles[j+1].port_pos == 3) || (i > 0 && ((i%2 == 0 && ((j < map.rows[i-1].row_len && map.rows[i-1].tiles[j].port_pos == 4) || (j < map.rows[i-1].row_len + 1 && map.rows[i-1].tiles[j-1].port_pos == 5))) || (i%2 == 1 && ((j < map.rows[i-1].row_len - 1 && map.rows[i-1].tiles[j+1].port_pos == 4) || (j < map.rows[i-1].row_len && map.rows[i-1].tiles[j].port_pos == 5))))) || (j > 0 && map.rows[i].tiles[j-1].port_pos == 0) || (i < map.num_rows - 1 && ((i%2 == 0 && ((j < map.rows[i+1].row_len && map.rows[i+1].tiles[j].port_pos == 2) || (j < map.rows[i+1].row_len + 1 && map.rows[i+1].tiles[j-1].port_pos == 1))) || (i%2 == 1 && ((j < map.rows[i+1].row_len - 1 && map.rows[i+1].tiles[j+1].port_pos == 2) || (j < map.rows[i+1].row_len && map.rows[i+1].tiles[j].port_pos == 1))))); } void randomize_ports (Map map) { int seed = time(NULL); int i; int j; Tile **ports; int k = 0; int rand_pos; int tmp_port_type; srand(seed); ports = (Tile **) malloc (sizeof(Tile *)*map.num_port); for (i = 0; i < map.num_rows; i++) for (j = 0; j < map.rows[i].row_len; j++) if (map.rows[i].tiles[j].port_type) { ports[k] = &map.rows[i].tiles[j]; k++; } for (i = 0; i < map.num_port; i++) { rand_pos = (rand () % map.num_port - i) + i; tmp_port_type = ports[i]->port_type; ports[i]->port_type = ports[rand_pos]->port_type; ports[rand_pos]->port_type = tmp_port_type; } free (ports); } void find_next_chit_num (Map map, int *x, int *y, int k) { int i = 0; int j = 0; while ((i < map.num_rows) && (map.rows[i].tiles[j].chit_num != k)) { while ((j < map.rows[i].row_len) && (map.rows[i].tiles[j].chit_num != k)) { j++; } if (map.rows[i].tiles[j].chit_num != k) { j = 0; i++; } } *x = i; *y = j; } int* randomize_chits (Map map, int *chits, int *num_chits) { int seed = time(NULL); int num_rand_chits = map.num_rand - map.num_rand_des; int k = 0; int x = 0; int y = 0; Coords *chit_hex; int num_prev_des = 0; int num_prev_not_rand = 0; int num_prev_missing = 0; int *tmp_chits; int *nchits; int first_high; int rand_chit; int replace_pos; nchits = (int *) malloc (sizeof(int)*(map.num_land - map.num_des)); int l; for (l = 0; l < map.num_land - map.num_des; l++) nchits[l] = chits[l % *num_chits]; free (chits); *num_chits = map.num_land - map.num_des; srand(seed); chit_hex = (Coords *) malloc (sizeof(Coords)*num_rand_chits); while (k < map.num_land + num_prev_missing) { find_next_chit_num (map, &x, &y, k); if (x >= map.num_rows) num_prev_missing++; else if (map.rows[x].tiles[y].tile_type == DESERT) { num_prev_des++; } else if (!map.rows[x].tiles[y].is_rand) { num_prev_not_rand++; if ((nchits[k - num_prev_des - num_prev_missing] == 6) || (nchits[k - num_prev_des - num_prev_missing] == 8)) map.rows[x].tiles[y].is_high = 1; } else { chit_hex[k-num_prev_des-num_prev_not_rand-num_prev_missing].x = x; chit_hex[k-num_prev_des-num_prev_not_rand-num_prev_missing].y = y; chit_hex[k-num_prev_des-num_prev_not_rand-num_prev_missing].chit_loc = k - num_prev_des - num_prev_missing; } k++; } tmp_chits = (int *) malloc (sizeof(int)*num_rand_chits); int i; for (i = 0; i < num_rand_chits; i++) { tmp_chits[i] = nchits[chit_hex[i].chit_loc]; } first_high = move_high_odds_to_end (tmp_chits, num_rand_chits); for (i = 0; i < num_rand_chits; i++) { if (high_is_adj (map, chit_hex[i].x, chit_hex[i].y)) { if (first_high == 0) { replace_pos = find_allowable_position (map, chit_hex, i); rand_chit = rand () % (num_rand_chits - i); int temp_chit = tmp_chits[rand_chit]; tmp_chits[rand_chit] = nchits[chit_hex[replace_pos].chit_loc]; nchits[chit_hex[replace_pos].chit_loc] = temp_chit; map.rows[chit_hex[replace_pos].x].tiles[chit_hex[replace_pos].y].is_high = 1; } else rand_chit = rand () % first_high; } else rand_chit = rand () % (num_rand_chits - i); nchits[chit_hex[i].chit_loc] = tmp_chits[rand_chit]; int l; for (l = rand_chit; l < num_rand_chits -i - 1; l++) { tmp_chits[l] = tmp_chits[l+1]; } if (rand_chit < first_high) first_high--; else if (nchits[chit_hex[i].chit_loc] == 6 || nchits[chit_hex[i].chit_loc] == 8) map.rows[chit_hex[i].x].tiles[chit_hex[i].y].is_high = 1; } return nchits; free (tmp_chits); free (chit_hex); } int find_allowable_position (Map map, Coords *chit_hex, int k) { int replace_pos = 0; int last_pos = -1; while (replace_pos < k) { if ((map.rows[chit_hex[replace_pos].x].tiles[chit_hex[replace_pos].y].is_high) || (high_is_adj (map, chit_hex[replace_pos].x, chit_hex[replace_pos].y))) replace_pos++; else { last_pos = replace_pos; if ((rand() % k) > (k/3)) replace_pos++; else break; } } if (last_pos < 0) { fprintf (stderr, "FATAL: Arrived at an impossible situation - could not prevent adjacent sixes and eights\n"); exit(1); } if (replace_pos >= k) replace_pos = last_pos; return replace_pos; } int move_high_odds_to_end (int *chits, int num_chits) { int first_high = num_chits; int i; while ((chits[first_high - 1] == 6) || (chits[first_high - 1] == 8)) first_high--; for (i = first_high - 1; i >= 0; i--) { if ((chits[i] == 6) || (chits[i] == 8)) { int tmp_chit = chits[first_high - 1]; chits[first_high - 1] = chits[i]; chits[i] = tmp_chit; first_high--; } } return first_high; } int high_is_adj (Map map, int i, int j) { return (j > 0 && map.rows[i].tiles[j-1].is_high) || (j < map.rows[i].row_len - 1 && map.rows[i].tiles[j+1].is_high) || (i > 0 && ((j < map.rows[i-1].row_len && map.rows[i-1].tiles[j].is_high) || (i%2 == 0 && j > 0 && map.rows[i-1].tiles[j-1].is_high) || (i%2 == 1 && j < map.rows[i-1].row_len - 1 && map.rows[i-1].tiles[j+1].is_high))) || (i < map.num_rows - 1 && ((j < map.rows[i+1].row_len && map.rows[i+1].tiles[j].is_high) || (i%2 == 0 && j > 0 && map.rows[i+1].tiles[j-1].is_high) || (i%2 == 1 && j < map.rows[i+1].row_len - 1 && map.rows[i+1].tiles[j+1].is_high))); } void write_chits (int *chits, int num_chits, FILE *fo) { int i; fprintf (fo, "chits "); for (i = 0; i < num_chits - 1; i++) fprintf (fo, "%d,", chits[i]); fprintf (fo, "%d", chits[num_chits - 1]); fprintf(fo, "\n"); } void write_map (Map map, FILE *fo) { fprintf (fo, "map\n"); int i; for (i = 0; i < map.num_rows; i++) { int j; for(j = 0; j < map.rows[i].row_len; j++) { switch (map.rows[i].tiles[j].tile_type) { case BOARD: fprintf (fo, "-"); break; case SEA: fprintf (fo, "s"); switch (map.rows[i].tiles[j].port_type) { case TIMBER_PORT: fprintf (fo, "l%d", map.rows[i].tiles[j].port_pos); break; case BRICK_PORT: fprintf (fo, "b%d", map.rows[i].tiles[j].port_pos); break; case GRAIN_PORT: fprintf (fo, "g%d", map.rows[i].tiles[j].port_pos); break; case ORE_PORT: fprintf (fo, "o%d", map.rows[i].tiles[j].port_pos); break; case WOOL_PORT: fprintf (fo, "w%d", map.rows[i].tiles[j].port_pos); break; case MULTI_PORT: fprintf (fo, "?%d", map.rows[i].tiles[j].port_pos); break; default: break; } break; case DESERT: fprintf (fo, "d"); break; case FOREST: fprintf (fo, "t"); break; case HILL: fprintf (fo, "h"); break; case MOUNTAIN: fprintf (fo, "m"); break; case PLAIN: fprintf (fo, "p"); break; case FIELD: fprintf (fo, "f"); break; case GOLD: fprintf (fo, "g"); break; default: break; } if (map.rows[i].tiles[j].tile_type > 1) { fprintf (fo, "%d", map.rows[i].tiles[j].chit_num); } if ((!map.rows[i].tiles[j].is_rand) && (map.rows[i].tiles[j].tile_type != BOARD)) fprintf (fo, "+"); if (j == map.rows[i].row_len - 1) fprintf (fo, "\n"); else fprintf (fo, ","); } } fprintf (fo, ".\n"); }