void kings_move(struct state *s) { int i; int ev = 1; for(i=0; i<s->kings_num; ++i) { int pl = s->king[i].pl; place_flags(&s->king[i], &s->grid, &s->fg[pl]); int code = builder_default(&s->king[i], &s->country[pl], &s->grid, &s->fg[pl]); ev = ev || (code == 0); } if (ev) { for(i=0; i<s->kings_num; ++i) { king_evaluate_map(&s->king[i], &s->grid, s->dif); } } }
void king_init (struct king *k, int pl, enum strategy strat, struct grid *g, enum config_dif dif) { k->pl = pl; k->strategy = strat; king_evaluate_map(k, g, dif); }
void state_init(struct state *s, struct basic_options *op, struct multi_options *mop){ s->speed = op->speed; s->prev_speed = s->speed; s->dif = op->dif; s->map_seed = op->map_seed; s->conditions = op->conditions; s->inequality = op->inequality; s->winlosecondition = 0; s->time = (1850 + rand()%100) * 360 + rand()%360; /* player controlled from the keyboard */ s->controlled = 1; /* int players[] = {7, 2, 3, 5}; */ /* int players[] = {2, 3, 4, 5, 6, 7}; */ int all_players[] = {1, 2, 3, 4, 5, 6, 7}; int comp_players[MAX_PLAYER]; int comp_players_num = 7 - mop->clients_num; s->kings_num = comp_players_num; int ui_players[MAX_PLAYER]; int ui_players_num = mop->clients_num; int i; for (i=0; i<7; ++i) { if (i<mop->clients_num) ui_players[i] = all_players[i]; else { int j = i - mop->clients_num; /* computer player index / king's index */ comp_players[j] = all_players[i]; switch (i){ case 1: king_init (&s->king[j], i+1, opportunist, &s->grid, s->dif); break; case 2: king_init (&s->king[j], i+1, one_greedy, &s->grid, s->dif); break; case 3: king_init (&s->king[j], i+1, none, &s->grid, s->dif); break; case 4: king_init (&s->king[j], i+1, aggr_greedy, &s->grid, s->dif); break; case 5: king_init (&s->king[j], i+1, noble, &s->grid, s->dif); break; case 6: king_init (&s->king[j], i+1, persistent_greedy, &s->grid, s->dif); break; } } } /* Initialize map generation with the map_seed */ srand(s->map_seed); /* Map generation starts */ { int conflict_code = 0; do { grid_init(&s->grid, op->w, op->h); /* starting locations arrays */ struct loc loc_arr[MAX_AVLBL_LOC]; int available_loc_num = 0; int d = 2; apply_stencil(op->shape, &s->grid, d, loc_arr, &available_loc_num); /* conflict mode */ conflict_code = 0; if (!op->keep_random_flag) conflict_code = conflict(&s->grid, loc_arr, available_loc_num, comp_players, comp_players_num, op->loc_num, ui_players, ui_players_num, s->conditions, s->inequality); } while(conflict_code != 0 || !is_connected(&s->grid)); } /* Map is ready */ int p; for(p = 0; p<MAX_PLAYER; ++p) { flag_grid_init(&s->fg[p], op->w, op->h); s->country[p].gold = 0; } /* kings evaluate the map */ for(p = 0; p < s->kings_num; ++p) { king_evaluate_map(&s->king[p], &s->grid, s->dif); } /* Zero timeline */ s->show_timeline = op->timeline_flag; s->timeline.mark = -1; for(i=0; i<MAX_TIMELINE_MARK; ++i) { s->timeline.time[i] = s->time; for(p=0; p<MAX_PLAYER; ++p) { s->timeline.data[p][i] = 0.0; } } /* init turn by turn */ for(p=0; p<mop->clients_num; ++p) { s->turn_validated[p] = 0; } }
void simulate(struct state *s) { int i, j; struct tile (* t) [MAX_HEIGHT] = s->grid.tiles; int enemy_pop [MAX_PLAYER]; int my_pop [MAX_PLAYER]; int need_to_reeval = 0; /* increment time */ s->time++; /* per tile events */ for(i=0; i<s->grid.width; ++i) { for(j=0; j<s->grid.height; ++j) { /* mines ownership */ if (t[i][j].cl == mine){ int k; int owner = NEUTRAL; for(k=0; k<DIRECTIONS; ++k) { int di = dirs[k].i; int dj = dirs[k].j; if( i+di >= 0 && i+di < s->grid.width && j+dj >= 0 && j+dj < s->grid.height && is_inhabitable (t[i+di][j+dj].cl) ) { int pl = t[i+di][j+dj].pl; if (owner == NEUTRAL) owner = pl; else if (owner != pl && pl != NEUTRAL) owner = -1; } } if (owner != -1) t[i][j].pl = owner; else t[i][j].pl = NEUTRAL; if (t[i][j].pl != NEUTRAL) s->country[owner].gold += 1; } /* fight */ int p; int total_pop = 0; for(p=0; p<MAX_PLAYER; ++p){ my_pop[p] = t[i][j].units[p][citizen]; total_pop += my_pop[p]; } int defender_dmg = 0; for(p=0; p<MAX_PLAYER; ++p){ enemy_pop[p] = total_pop - my_pop[p]; int dmg = rnd_round( (float)enemy_pop[p] * my_pop[p] / total_pop ); t[i][j].units[p][citizen] = MAX(my_pop[p] - dmg, 0); if (t[i][j].pl == p) defender_dmg = dmg; } /* burning cities */ if (defender_dmg > 2.0 * MAX_POP * ATTACK && is_a_city(t[i][j].cl)) { if (rand() % 1 == 0){ need_to_reeval = 1; degrade (&s->grid, i, j); } } /* determine ownership */ if (is_inhabitable(t[i][j].cl)){ t[i][j].pl = NEUTRAL; for(p=0; p<MAX_PLAYER; ++p){ if (t[i][j].units[p][citizen] > t[i][j].units[t[i][j].pl][citizen]) { t[i][j].pl = p; } } } if (is_a_city(t[i][j].cl)) { /* population growth */ int owner = t[i][j].pl; int pop = t[i][j].units[owner][citizen]; float fnpop = (float) pop * growth(t[i][j].cl); int npop = rnd_round(fnpop); npop = MIN(npop, MAX_POP); /* death */ //npop = npop - rnd_round(0.01*pow(pop,1.5)); //npop = npop - rnd_round(1.0e-20 * pow(2.0,pop)); //npop = MAX(npop, 0); t[i][j].units[owner][citizen] = npop; } } } /* migration */ int k, di, dj, p; int i_start, i_end, i_inc; int j_start, j_end, j_inc; if(rand()%2 == 0) { i_start = 0; i_end = s->grid.width; i_inc = 1; } else { i_start = s->grid.width-1; i_end = -1; i_inc = -1; } if(rand()%2 == 0) { j_start = 0; j_end = s->grid.height; j_inc = 1; } else { j_start = s->grid.height-1; j_end = -1; j_inc = -1; } for(i=i_start; i!=i_end; i+=i_inc) { for(j=j_start; j!=j_end; j+=j_inc) { for(p=0; p<MAX_PLAYER; ++p){ int initial_pop = t[i][j].units[p][citizen]; int k_shift = rand() % DIRECTIONS; for(k=0; k<DIRECTIONS; ++k) { di = dirs[(k + k_shift) % DIRECTIONS].i; dj = dirs[(k + k_shift) % DIRECTIONS].j; if( i+di >= 0 && i+di < s->grid.width && j+dj >= 0 && j+dj < s->grid.height && is_inhabitable (t[i+di][j+dj].cl) ) { int pop = t[i][j].units[p][citizen]; int dcall = MAX(0, s->fg[p].call[i+di][j+dj] - s->fg[p].call[i][j]); if (pop > 0) { int dpop = rnd_round (MOVE * initial_pop + CALL_MOVE * dcall * initial_pop); dpop = MIN(dpop, pop); dpop = MIN(dpop, MAX_POP - t[i+di][j+dj].units[p][citizen]); t[i+di][j+dj].units[p][citizen] += dpop; t[i][j].units[p][citizen] -= dpop; } } } } } } /* determine ownership again */ for(i=0; i<s->grid.width; ++i) { for(j=0; j<s->grid.height; ++j) { if (is_inhabitable(t[i][j].cl)){ t[i][j].pl = NEUTRAL; for(p=0; p<MAX_PLAYER; ++p){ if (t[i][j].units[p][citizen] > t[i][j].units[t[i][j].pl][citizen]) { t[i][j].pl = p; } } } } } /* Kings reevaluate the map */ if(need_to_reeval) { for(i=0; i<s->kings_num; ++i) { king_evaluate_map(&s->king[i], &s->grid, s->dif); } } /* give gold to AI on hard difficulties */ int add_gold = 0; switch(s->dif) { case dif_hard: add_gold = 1; break; case dif_hardest: add_gold = 2; break; default: ; } for(i=0; i<MAX_PLAYER; ++i){ if (i != NEUTRAL && i != s->controlled && s->country[i].gold>0) s->country[i].gold += add_gold; } }