/************************************************************************* What is type of the traderoute between two cities. *************************************************************************/ enum trade_route_type cities_trade_route_type(const struct city *pcity1, const struct city *pcity2) { if (city_owner(pcity1) != city_owner(pcity2)) { if (city_tile(pcity1)->continent != city_tile(pcity2)->continent) { return TRT_IN_IC; } else { return TRT_IN; } } else { if (city_tile(pcity1)->continent != city_tile(pcity2)->continent) { return TRT_NATIONAL_IC; } else { return TRT_NATIONAL; } } return TRT_LAST; }
/**************************************************************************** Returns the basic structure filled with initial elements. ****************************************************************************/ struct vision_site *create_vision_site_from_city(const struct city *pcity) { struct vision_site *psite = create_vision_site(pcity->id, city_tile(pcity), city_owner(pcity)); psite->size = pcity->size; sz_strlcpy(psite->name, city_name(pcity)); return psite; }
/**************************************************************** Callback from diplomat/spy dialog for "keep moving". (This should only occur when entering allied city.) *****************************************************************/ static void diplomat_keep_moving_callback(GtkWidget *w, gpointer data) { struct unit *punit; struct city *pcity; if ((punit = game_unit_by_number(diplomat_id)) && (pcity = game_city_by_number(diplomat_target_id)) && !same_pos(unit_tile(punit), city_tile(pcity))) { request_diplomat_action(DIPLOMAT_MOVE, diplomat_id, diplomat_target_id, 0); } gtk_widget_destroy(diplomat_dialog); }
/*************************************************************************** Client variant of city_tile(). This include the case of this could a ghost city (see client/packhand.c). In a such case, the returned tile is an approximative position of the city on the map. ***************************************************************************/ struct tile *client_city_tile(const struct city *pcity) { int dx, dy; double x = 0, y = 0; size_t num = 0; if (NULL == pcity) { return NULL; } if (NULL != city_tile(pcity)) { /* Normal city case. */ return city_tile(pcity); } whole_map_iterate(ptile) { int tile_x, tile_y; index_to_map_pos(&tile_x, &tile_y, tile_index(ptile)); if (pcity == tile_worked(ptile)) { if (0 == num) { x = tile_x; y = tile_y; num = 1; } else { num++; base_map_distance_vector(&dx, &dy, (int)x, (int)y, tile_x, tile_y); x += (double) dx / num; y += (double) dy / num; } } } whole_map_iterate_end; if (0 < num) { return map_pos_to_tile((int) x, (int) y); } else { return NULL; } }
/**************************************************************** Callback from diplomat/spy dialog for "keep moving". (This should only occur when entering allied city.) *****************************************************************/ static int diplomat_keep_moving_callback(struct widget *pWidget) { if (Main.event.button.button == SDL_BUTTON_LEFT) { struct unit *punit; struct city *pcity; if ((punit = game_unit_by_number(pDiplomat_Dlg->diplomat_id)) && (pcity = game_city_by_number(pDiplomat_Dlg->diplomat_target_id)) && !same_pos(unit_tile(punit), city_tile(pcity))) { request_diplomat_action(DIPLOMAT_MOVE, pDiplomat_Dlg->diplomat_id, pDiplomat_Dlg->diplomat_target_id, 0); } popdown_diplomat_dialog(); } return -1; }
/************************************************************************** Callback from diplomat/spy dialog for "keep moving". (This should only occur when entering allied city.) **************************************************************************/ static void diplomat_keep_moving_callback(Widget w, XtPointer client_data, XtPointer call_data) { struct unit *punit; struct city *pcity; destroy_message_dialog(w); diplomat_dialog = NULL; if ((punit = game_unit_by_number(diplomat_id)) && (pcity = game_city_by_number(diplomat_target_id)) && !same_pos(unit_tile(punit), city_tile(pcity))) { request_diplomat_action(DIPLOMAT_MOVE, diplomat_id, diplomat_target_id, 0); } process_diplomat_arrival(NULL, 0); }
/************************************************************************** Returns city_tile_value of the best tile worked by or available to pcity. **************************************************************************/ static int best_worker_tile_value(struct city *pcity) { struct tile *pcenter = city_tile(pcity); int best = 0; city_tile_iterate(city_map_radius_sq_get(pcity), pcenter, ptile) { if (is_free_worked(pcity, ptile) || tile_worked(ptile) == pcity /* quick test */ || city_can_work_tile(pcity, ptile)) { int tmp = city_tile_value(pcity, ptile, 0, 0); if (best < tmp) { best = tmp; } } } city_tile_iterate_end; return best; }
/************************************************************************** Is an evalutaion of the requirement accurate when pow_player evaluates it? Note: Assumed to use pow_player's data. TODO: Move the data to a data file. That will - let non programmers help complete it and/or fix what is wrong - let clients not written in C use the data **************************************************************************/ static bool is_req_knowable(const struct player *pow_player, const struct player *target_player, const struct player *other_player, const struct city *target_city, const struct impr_type *target_building, const struct tile *target_tile, const struct unit_type *target_unittype, const struct output_type *target_output, const struct specialist *target_specialist, const struct requirement *req) { fc_assert_ret_val_msg(NULL != pow_player, false, "No point of view"); if ((req->source.kind == VUT_UTFLAG || req->source.kind == VUT_UTYPE) && target_unittype != NULL) { return TRUE; } if (req->source.kind == VUT_DIPLREL && pow_player == target_player && (req->range == REQ_RANGE_LOCAL || req->range == REQ_RANGE_PLAYER)) { return TRUE; } if (req->source.kind == VUT_MINSIZE && target_city != NULL) { enum known_type vision = tile_get_known(city_tile(target_city), pow_player); if (vision == TILE_KNOWN_SEEN || city_owner(target_city) == pow_player) { return TRUE; } } if (req->source.kind == VUT_CITYTILE && req->range == REQ_RANGE_LOCAL) { enum known_type vision = tile_get_known(target_tile, pow_player); if (vision == TILE_KNOWN_SEEN || (target_city && city_owner(target_city) == pow_player)) { return TRUE; } } if (req->source.kind == VUT_NATION) { return TRUE; } if (req->source.kind == VUT_ADVANCE || req->source.kind == VUT_TECHFLAG) { if (req->range == REQ_RANGE_PLAYER && (pow_player == target_player || player_has_embassy(pow_player, target_player))) { return TRUE; } } if (req->source.kind == VUT_GOVERNMENT) { if (req->range == REQ_RANGE_PLAYER && (pow_player == target_player || could_intel_with_player(pow_player, target_player))) { return TRUE; } } /* Uncertain or no support added yet. */ return FALSE; }
} city_tile_iterate_end; return best; } /************************************************************************** Do all tile improvement calculations and cache them for later. These values are used in settler_evaluate_improvements() so this function must be called before doing that. Currently this is only done when handling auto-settlers or when the AI contemplates building worker units. **************************************************************************/ void initialize_infrastructure_cache(struct player *pplayer) { city_list_iterate(pplayer->cities, pcity) { struct tile *pcenter = city_tile(pcity); int radius_sq = city_map_radius_sq_get(pcity); int best = best_worker_tile_value(pcity); city_map_iterate(radius_sq, city_index, city_x, city_y) { activity_type_iterate(act) { adv_city_worker_act_set(pcity, city_index, act, -1); } activity_type_iterate_end; } city_map_iterate_end; city_tile_iterate_index(radius_sq, pcenter, ptile, cindex) { adv_city_worker_act_set(pcity, cindex, ACTIVITY_POLLUTION, adv_calc_pollution(pcity, ptile, best)); adv_city_worker_act_set(pcity, cindex, ACTIVITY_FALLOUT, adv_calc_fallout(pcity, ptile, best)); adv_city_worker_act_set(pcity, cindex, ACTIVITY_MINE,