#include #include #include "constant.h" /**** x include files ****/ #include #include #include #include #include #if USE_LONGJMP #include #endif #include "extern.h" /****************************************************************************** init_board () Create the game board and initialize each cell of the board. ******************************************************************************/ init_board () { int i, j, k, side; cell_type *cell; /** Initialize statistics **/ for (side=0; sideside_count; side++) { Config->stats[side] = (statistic_type *)(malloc(sizeof(statistic_type))); Config->stats[side]->build_count = 0; Config->stats[side]->troop_count = 0; Config->stats[side]->cell_count = 0; } /** Initialize random number generator **/ srand((long)Config->value_int_all[OPTION_SEED]); printf ("seed: %d\n", Config->value_int_all[OPTION_SEED]); /** Initialize the global structure **/ Board = (board_type *)(malloc(sizeof(board_type))); Board->cell_count = 0; /** Allocate all cells and their dynamic components **/ for (j=0; jboard_y_size; j++) for (i=0; iboard_x_size; i++) { cell = (cell_type *)(malloc(sizeof(cell_type))); Board->cells[j][i] = cell; Board->list[Board->cell_count++] = cell; cell->dir = (s_char *)(malloc(sizeof(s_char)*(Config->direction_count))); cell->value = (s_char *)(malloc(sizeof(s_char)*(Config->side_count))); cell->march = (s_char *)(malloc(sizeof(s_char)*(Config->side_count))); cell->march_type =(s_char *)(malloc(sizeof(s_char)*(Config->side_count))); cell->march_dir = (s_char *)(malloc(sizeof(s_char)*(Config->side_count))); cell->seen = (s_char *)(malloc(sizeof(s_char)*(Config->side_count))); cell->draw_level = (s_char *)(malloc(sizeof(s_char)*(Config->side_count))); cell->x_center = (short *)(malloc(sizeof(short)*(Config->side_count))); cell->y_center = (short *)(malloc(sizeof(short)*(Config->side_count))); } /** Initialize each cell's values **/ for (j=0; jboard_y_size; j++) { /** For each column **/ for (i=0; iboard_x_size; i++) { cell = CELL2(i,j); /** Initialize salient variables **/ cell->x = i; cell->y = j; cell->side = SIDE_NONE; cell->old_side = SIDE_NONE; cell->lowbound = 0; cell->growth = 0; cell->old_growth = 0; cell->angle = 0; cell->age = 0; cell->any_march = FALSE; cell->move = 0; cell->manage_update = FALSE; cell->manage_x = 0; cell->manage_y = 0; cell->level = 0; cell->side_count = 0; cell->shape_index = 0; cell->outdated = OUTDATE_ALL; cell->redraw_status = REDRAW_NORMAL; cell->old_value = -1; /** Set all parameters of side-varying nature **/ for (side=0; sideside_count; side++) { cell->value[side] = 0; cell->march[side] = FALSE; cell->seen[side] = TRUE; cell->draw_level[side] = 0; } /** Null out all direction vectors **/ for (k=0; kdirection_count; k++) cell->dir[k] = 0; /** NOTE: cell position defined in shape_initialize() **/ } } /** Load board from file if specified **/ if (Config->enable_all[OPTION_LOAD]) load_board (Config->use_brief_load); /** Initialize all the tiling-dependent aspects of the board **/ shape_initialize (); /** If using interactive edit, create some terrain if using overwrite **/ if (Config->enable_all[OPTION_EDIT]) { if (Config->enable_all[OPTION_OVERWRITE] && !Config->enable_all[OPTION_LOAD]) init_terrain (); return; } if (Config->enable_terrain && !Config->enable_all[OPTION_LOAD]) init_terrain (); /** Initialize var self-explanatory aspects of the board **/ if (Config->enable_all[OPTION_FARMS]) init_farms (); if (Config->enable_all[OPTION_TOWNS]) init_towns (); if (Config->enable_all[OPTION_BASES]) init_bases_or_armies (OPTION_BASES); if (Config->enable_all[OPTION_RBASES]) init_rbases (); if (Config->enable_all[OPTION_ARMIES]) init_bases_or_armies (OPTION_ARMIES); if (Config->enable_all[OPTION_MILITIA]) init_militia (TRUE); /** Initialize visibility of each cell **/ if (!Config->enable_all[OPTION_LOAD] || Config->enable_all[OPTION_OVERWRITE]) init_unseen (); } /****************************************************************************** init_unseen () If using any type of map-as-you-go option set, render all cells unseen. ******************************************************************************/ init_unseen () { int i, side; for (side=0; sideside_count; side++) { if (Config->enable[OPTION_MAP][side] || Config->enable[OPTION_LOCALMAP][side]) { for (i=0; icell_count; i++) CELL(i)->seen[side] = FALSE; } } } /****************************************************************************** init_terrain () Initialize hills, forests, and seas across the game board using a peak algorithm developed by Jack Bennetto (bennetto@physics.rutgers.edu), with analogous trough algorithm tacked on. ******************************************************************************/ init_terrain () { int i, j, k, x_peak[MAX_PEAKS], y_peak[MAX_PEAKS], z_peak[MAX_PEAKS], elevation_bin[ELEVATION_BINS], elevation_to_level[ELEVATION_BINS], peak_count, cell_count, level_count, cell_limit, level, bin_index, dist_squared; double denominator, elevation[MAX_BOARDSIZE][MAX_BOARDSIZE], fractions[100], fraction, pow(), sea_base_fraction; cell_type *cell; /** Determine the number of peaks (and troughs **/ peak_count = (int)(Config->value_int_all[OPTION_PEAKS] * Board->cell_count * PEAK_MULTIPLIER); if (peak_count > MAX_PEAKS) peak_count = MAX_PEAKS; /** For each peak, set random position and height **/ for (i=0; iboard_x_size); y_peak[i] = get_random (Config->board_y_size); z_peak[i] = get_random (ELEVATION_BINS) - ELEVATION_OFFSET; } /** Zero out the elevation bins **/ for (i=0; iboard_x_size; i++) for (j=0; jboard_y_size; j++) { cell = CELL2(i,j); elevation[i][j] = 0.0; denominator = 0.0; /** For each peak, add elevation to cell, normalizing by the **/ /** square root of the distance to the peak. **/ for (k=0; kvalue_double_all[OPTION_SEA]/10.0; fraction = 0.0; /** Compute the biased fraction of cells at each sea level **/ if (Config->level_min < 0) { level_count = -Config->level_min; for (level = -1; level >= Config->level_min; level--) { fraction = pow ((double)(-level), Config->value_double_all[OPTION_TROUGH_BIAS])/level_count; fractions[level - Config->level_min] = fraction; } /** Normalize values **/ fraction = sea_base_fraction/fractions[0]; for (level = Config->level_min; level < -1; level++) fractions[level - Config->level_min] = sea_base_fraction - fraction * fractions[level - Config->level_min + 1]; fractions[level - Config->level_min] = sea_base_fraction; } /** Compute the biased fraction of cells at each non-sea level **/ level_count = Config->level_max + 1; for (level = 0; level <= Config->level_max; level++) { fraction = pow ((double)(level+1), Config->value_double_all[OPTION_PEAK_BIAS])/level_count; fractions[level - Config->level_min] = fraction; } /** Normalize values **/ fraction = (1.0 - sea_base_fraction)/ fractions[Config->level_max - Config->level_min]; for (level = 0; level <= Config->level_max; level++) fractions[level - Config->level_min] = sea_base_fraction + fraction * fractions[level - Config->level_min]; cell_count = 0; bin_index = 0; /** Set the actual levels by incrementally stepping through the **/ /** elevation bins and comparing count to fractional levels specified **/ /** by above computations. **/ for (level = Config->level_min; level <= Config->level_max; level++) { cell_limit = fractions[level - Config->level_min] * Board->cell_count; for (; cell_count < cell_limit && bin_index < ELEVATION_BINS; bin_index++) { cell_count += elevation_bin[bin_index]; elevation_to_level[bin_index] = level; } } /** Set the remainder of the bins to the highest level **/ for (; bin_indexlevel_max; /** Set level of each cell **/ for (i=0; iboard_x_size; i++) for (j=0; jboard_y_size; j++) { cell = CELL2(i,j); cell->level = elevation_to_level[ELEVATION_OFFSET + (int)(elevation[i][j])]; if (Config->enable_all[OPTION_SEA_BLOCK] && cell->level < 0) cell->level = Config->level_min; } } /****************************************************************************** init_towns () Initialize troop producing towns randomly across the game board. ******************************************************************************/ init_towns () { int i; for (i=0; icell_count; i++) if (get_random (100) <= Config->value_int_all[OPTION_TOWNS]*TOWN_MULTIPLIER) { if (CELL(i)->level >= 0) { CELL(i)->growth = TOWN_MIN + get_random (TOWN_MAX-TOWN_MIN); CELL(i)->old_growth = CELL(i)->growth; CELL(i)->angle = ANGLE_FULL; } } } /****************************************************************************** init_farms () Initialize troop producing farms uniformly across the game board. ******************************************************************************/ init_farms () { int i, j; for (i=0; icell_count; i++) if (CELL(i)->level >= 0) { if (CELL(i)->growth < TOWN_MIN) CELL(i)->growth = (int)(Config->value_int_all[OPTION_FARMS]); } } /****************************************************************************** init_rbases () Initialize troop producing bases (occupied big cities) randomly across game board, never putting opposite side bases so close together that they can be seen within the horizon. ******************************************************************************/ init_rbases () { int i, j, k, x, y, i1, i2, j1, j2, side, range, max_rbase_count, done, count; /** Determine maximum number of rbases **/ max_rbase_count = 0; for (side=0; sideside_count; side++) if (Config->value_int[OPTION_RBASES][side] > max_rbase_count) max_rbase_count = Config->value_int[OPTION_RBASES][side]; /** Set the minimum distance between rbases of opposing side **/ if (Config->view_range_max < Config->value_int_all[OPTION_RBASE_RANGE]) range = Config->value_int_all[OPTION_RBASE_RANGE]; else range = Config->view_range_max; /** Create rbases, alternating between sides **/ for (k=0; kside_count; side++) { if (!Config->enable[OPTION_RBASES][side]) continue; if (k >= Config->value_int[OPTION_RBASES][side]) continue; /** Keep trying to create an rbase far enough away from enemies **/ done = FALSE; count = 0; while (!done) { done = TRUE; /** Pick a random location on the game board **/ i = get_random (Config->board_x_size); j = get_random (Config->board_y_size); /** If location is already a base or town, forget it **/ if (CELL2(i,j)->growth > TOWN_MIN || CELL2(i,j)->level < 0) done = FALSE; /** Check neighboring locations for enemy bases **/ i1 = i-range; i2 = i+range; j1 = j-range; j2 = j+range; if (Config->enable_all[OPTION_WRAP]) { for (x=i1; x<=i2; x++) for (y=j1; y<=j2; y++) if (CELL2(MODX(x),MODY(y))->side != side && CELL2(MODX(x),MODY(y))->side != SIDE_NONE) done = FALSE; } else { i1 = (i1<0) ? 0 : i1; i2 = (i2>Config->board_x_size-1) ? Config->board_x_size-1 : i2; j1 = (j1<0) ? 0 : j1; j2 = (j2>Config->board_y_size-1) ? Config->board_y_size-1 : j2; for (x=i1; x<=i2; x++) for (y=j1; y<=j2; y++) if (CELL2(x,y)->side != side && CELL2(x,y)->side != SIDE_NONE) done = FALSE; } count++; /** If haven't found a valid location after 1000 tries, exit **/ if (count > 1000) done = TRUE; } /** If found a valid location, set up base **/ if (count < 1000) init_single_cell (CELL2(i,j), side, 1, 100); } } } /****************************************************************************** init_bases_or_armies (option) Initialize regular lines of armies or bases (depending on