Project

General

Profile

Feature #1791 » 1791.patch

John Robertson, 11/30/2025 12:31 PM

View differences:

ai/default/daiferry.c
aiferry_psngr_meet_boat(ait, punit, ferryboat);
punit->goto_tile = dest_tile;
punit->worker_activity = ACTIVITY_LAST;
punit->worker_target = NULL;
/* Grab bodyguard */
if (bodyguard
&& !same_pos(unit_tile(punit), unit_tile(bodyguard))) {
......
aunit->id,
TILE_XY(unit_tile(aunit)));
pferry->goto_tile = unit_tile(aunit);
pferry->worker_activity = ACTIVITY_LAST;
pferry->worker_target = NULL;
/* Exchange phone numbers */
aiferry_psngr_meet_boat(ait, aunit, pferry);
pf_map_destroy(pfm);
......
"find something better",
city_name_get(pcity));
pferry->goto_tile = pos.tile;
pferry->worker_activity = ACTIVITY_IDLE;
pferry->worker_target = NULL;
turns_horizon = turns;
needed = TRUE;
}
......
if (safe_city != nullptr) {
punit->goto_tile = safe_city->tile;
punit->worker_activity = ACTIVITY_IDLE;
punit->worker_target = NULL;
UNIT_LOG(LOGLEVEL_FERRY, punit, "No work, going home");
unit_data->done = TRUE;
dai_unit_new_task(ait, punit, AIUNIT_NONE, nullptr);
ai/default/daihunter.c
}
missile->goto_tile = unit_tile(sucker);
missile->worker_activity = ACTIVITY_PILLAGE;
missile->worker_target = NULL;
if (dai_unit_goto(ait, missile, unit_tile(sucker))) {
/* We survived; did they? */
sucker = game_unit_by_number(target_sanity); /* Sanity */
ai/default/daisettler.c
struct unit *punit, struct workermap *state)
{
adv_want best_impr = 0; /* Value of best terrain improvement we can do */
enum unit_activity best_act;
struct extra_type *best_target;
enum unit_activity best_act = ACTIVITY_IDLE;
struct extra_type *best_target = NULL;
struct tile *best_tile = NULL;
struct pf_path *path = NULL;
struct city *pcity = NULL;
/* Time it will take worker to complete its given task */
int completion_time = 0;
......
* unavailable, call it off. */
if (!city_can_be_built_here(nmap, ptile, punit, FALSE)) {
dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
UNIT_LOG(LOG_DEBUG, punit, "dai_auto_settler_run set to IDLE - %s:%d",
__FILE__, __LINE__);
set_unit_activity(punit, ACTIVITY_IDLE, ACTION_NONE);
send_unit_info(NULL, punit);
......
/*** Try find some work ***/
if (unit_has_type_flag(punit, UTYF_WORKERS)) {
struct worker_task *best_task;
TIMING_LOG(AIT_WORKERS, TIMER_START);
/* Have nearby cities requests? */
pcity = worker_evaluate_city_requests(punit, &best_task, &path, state);
worker_evaluate_city_requests(punit, &path, state);
if (pcity != NULL) {
if (punit->worker_activity != ACTIVITY_IDLE) {
if (path != NULL) {
completion_time = pf_path_last_position(path)->turn;
best_impr = 1;
best_act = best_task->act;
best_target = best_task->tgt;
best_tile = best_task->ptile;
best_act = punit->worker_activity;
best_target = punit->worker_target;
best_tile = punit->goto_tile;
} else {
pcity = NULL;
punit->worker_activity = ACTIVITY_IDLE;
punit->worker_target = NULL;
punit->goto_tile = NULL;
}
}
if (pcity == NULL) {
if (best_impr) {
best_impr = worker_evaluate_improvements(nmap, punit,
&best_act, &best_target,
&best_tile, &path, state);
......
citymap_reserve_tile(result->best_other.tile, punit->id);
}
punit->goto_tile = result->tile; /* TMP */
punit->worker_activity = ACTIVITY_LAST;
punit->worker_target = NULL;
cityresult_destroy(result);
......
adv_unit_new_task(punit, AUT_AUTO_WORKER, best_tile);
}
if (best_tile != NULL
&& auto_worker_setup_work(nmap, pplayer, punit, state, 0, &path,
best_tile, best_act, &best_target,
completion_time)) {
if (pcity != NULL) {
clear_worker_tasks(pcity);
}
if (best_impr && best_tile != NULL) {
auto_worker_setup_work(nmap, pplayer, punit, state, 0, &path, best_tile,
best_act, best_target, completion_time);
}
CLEANUP:
ai/default/daitools.c
* if we are on a ferry */
if (goto_is_sane(punit, dest_tile) && punit->moves_left > 0) {
punit->goto_tile = dest_tile;
punit->worker_activity = ACTIVITY_LAST;
punit->worker_target = NULL;
UNIT_LOG(LOGLEVEL_GOTHERE, punit, "Walking to (%d,%d)", TILE_XY(dest_tile));
if (!dai_unit_goto(ait, punit, dest_tile)) {
/* Died */
......
if (is_ferry) {
/* Show the destination in the client when watching an AI: */
punit->goto_tile = ptile;
punit->worker_activity = ACTIVITY_LAST;
punit->worker_target = NULL;
}
}
......
/* Verify and set the goto destination. Eventually this can be a lot more
* stringent, but for now we don't want to break things too badly. */
punit->goto_tile = ptile; /* May be nullptr. */
// punit->worker_activity = ACTIVITY_LAST;
// punit->worker_target = NULL;
if (unit_data->task == AIUNIT_NONE && bodyguard) {
dai_unit_new_task(ait, bodyguard, AIUNIT_NONE, nullptr);
ai/default/daiunit.c
CHECK_UNIT(punit);
if (dest) {
if (dest && punit->goto_tile != nullptr) {
ptile = punit->goto_tile;
} else {
ptile = unit_tile(punit);
......
invasion_funct(ait, aunit, TRUE, 0,
(unit_can_take_over(aunit)
? INVASION_OCCUPY : INVASION_ATTACK));
if ((pcity = tile_city(aunit->goto_tile))) {
if (aunit->goto_tile != nullptr
&& (pcity = tile_city(aunit->goto_tile))) {
struct ai_city *city_data = def_ai_city_data(pcity, ait);
city_data->attack += adv_unit_att_rating(aunit);
......
* adv_follow_path(). This way other units will know we're
* on our way even if we don't reach target yet. */
punit->goto_tile = dest_tile;
punit->worker_activity = ACTIVITY_LAST;
punit->worker_target = NULL;
unit_activity_handling(punit, ACTIVITY_GOTO, ACTION_NONE);
if (path != nullptr && !adv_follow_path(punit, path, dest_tile)) {
/* Died. */
ai/tex/texaicity.c
data->task.ptile = task.ptile;
data->task.act = task.act;
data->task.tgt = task.tgt;
data->task.want = task.want;
data->task.wanted = task.wanted;
data->task.enroute = task.enroute;
data->task.placed = task.placed;
texai_send_req(TEXAI_REQ_WORKER_TASK, pplayer, data);
}
......
action_id_get_activity(act));
if (tile_worked(ptile) == pcity) {
if ((value - orig_value) * TWMP > worked->want) {
worked->want = TWMP * (value - orig_value);
if ((value - orig_value) * TWMP > worked->wanted) {
worked->wanted = TWMP * (value - orig_value);
worked->ptile = ptile;
worked->act = action_id_get_activity(act);
worked->tgt = NULL;
......
ptile,
TRUE,
ptile, tgt))) {
state->wants[utype_index(unit_type_get(punit))] += worked->want;
state->wants[utype_index(unit_type_get(punit))] += worked->wanted;
}
} unit_list_iterate_end;
}
......
if (value > orig_value && value > state->uw_max) {
state->uw_max = value;
state->uw_max_base = value;
unworked->want = TWMP * (value - orig_value);
unworked->wanted = TWMP * (value - orig_value);
unworked->ptile = ptile;
unworked->act = action_id_get_activity(act);
unworked->tgt = NULL;
......
ptile,
TRUE,
ptile, tgt))) {
state->wants[utype_index(unit_type_get(punit))] += unworked->want;
state->wants[utype_index(unit_type_get(punit))] += unworked->wanted;
}
} unit_list_iterate_end;
}
......
value = base_value + extra;
if (tile_worked(ptile) == pcity) {
if ((value - orig_value) * TWMP > worked->want) {
worked->want = TWMP * (value - orig_value);
if ((value - orig_value) * TWMP > worked->wanted) {
worked->wanted = TWMP * (value - orig_value);
worked->ptile = ptile;
worked->act = action_get_activity(paction);
worked->tgt = tgt;
......
punit, unit_home(punit), ptile,
TRUE,
ptile, tgt))) {
state->wants[utype_index(unit_type_get(punit))] += worked->want;
state->wants[utype_index(unit_type_get(punit))] += worked->wanted;
}
} unit_list_iterate_end;
}
......
if (value > orig_value && value > state->uw_max) {
state->uw_max = value;
state->uw_max_base = base_value;
unworked->want = TWMP * (value - orig_value);
unworked->wanted = TWMP * (value - orig_value);
unworked->ptile = ptile;
unworked->act = action_get_activity(paction);
unworked->tgt = tgt;
......
punit, unit_home(punit), ptile,
TRUE,
ptile, tgt))) {
state->wants[utype_index(unit_type_get(punit))] += unworked->want;
state->wants[utype_index(unit_type_get(punit))] += unworked->wanted;
}
} unit_list_iterate_end;
}
......
enum texai_worker_task_limitation limit)
{
struct worker_task *selected;
struct worker_task worked = { .ptile = NULL, .want = 0, .act = ACTIVITY_IDLE, .tgt = NULL };
struct worker_task unworked = { .ptile = NULL, .want = 0, .act = ACTIVITY_IDLE, .tgt = NULL };
struct texai_tile_state state = { .uw_max = 0, .uw_max_base = 0, .worst_worked = FC_INFINITY,
.orig_worst_worked = 0, .old_worst_worked = FC_INFINITY };
struct worker_task worked = { .ptile = NULL, .wanted = 0, .enroute = 0,
.placed = 0, .act = ACTIVITY_IDLE, .tgt = NULL };
struct worker_task unworked = { .ptile = NULL, .wanted = 0, .enroute = 0,
.placed = 0, .act = ACTIVITY_IDLE, .tgt = NULL };
struct texai_tile_state state = { .uw_max = 0, .uw_max_base = 0,
.worst_worked = FC_INFINITY,
.orig_worst_worked = 0,
.old_worst_worked = FC_INFINITY };
struct unit_list *units = NULL;
const struct civ_map *nmap = &(wld.map);
......
if (worked.ptile == NULL
|| (state.old_worst_worked < state.uw_max
&& (state.uw_max - state.orig_worst_worked) * TWMP > worked.want)
|| (state.uw_max - state.uw_max_base * TWMP > worked.want)) {
&& (state.uw_max - state.orig_worst_worked) * TWMP > worked.wanted)
|| (state.uw_max - state.uw_max_base * TWMP > worked.wanted)) {
/* It's better to improve best yet unworked tile and take it to use after that,
than to improve already worked tile. OR it's more important to
improve road connectivity outside worked tiles than improve worked tiles */
......
task->ptile = selected->ptile;
task->act = selected->act;
task->tgt = target;
task->want = selected->want;
task->wanted = selected->wanted;
task->enroute = selected->enroute;
task->placed = selected->placed;
return TRUE;
}
......
if (pcity != NULL && city_owner(pcity) == req->plr) {
/* City has not been lost meanwhile */
struct worker_task *ptask = worker_task_list_get(pcity->task_reqs, 0);
if (ptask == NULL) {
ptask = fc_malloc(sizeof(struct worker_task));
worker_task_init(ptask);
worker_task_list_append(pcity->task_reqs, ptask);
}
worker_task_create(pcity->task_reqs, data->task.ptile, data->task.act,
data->task.tgt, data->task.wanted );
log_debug("%s storing req for act %d at (%d,%d)",
pcity->name, data->task.act, TILE_XY(data->task.ptile));
ptask->ptile = data->task.ptile;
ptask->act = data->task.act;
ptask->tgt = data->task.tgt;
ptask->want = data->task.want;
/* Send info to observers */
package_and_send_worker_tasks(pcity);
client/gui-gtk-3.22/citydlg.c
if (act == ACTIVITY_LAST) {
task.tgt = -1;
task.want = 0;
task.wanted = 0;
} else {
enum extra_cause cause = activity_to_extra_cause(act);
enum extra_rmcause rmcause = activity_to_extra_rmcause(act);
......
}
task.tgt = -1;
task.wanted = 0;
} else {
task.tgt = extra_index(tgt);
switch (task.activity)
{
case ACTIVITY_CLEAN:
task.wanted = CITY_ACTIVITY_MEDIUM_WANTED;
break;
case ACTIVITY_CONVERT:
case ACTIVITY_CULTIVATE:
case ACTIVITY_PLANT:
case ACTIVITY_TRANSFORM:
task.wanted = CITY_ACTIVITY_MAX_WANTED;
break;
default:
task.wanted = CITY_ACTIVITY_DEFAULT_WANTED;
break;
}
}
task.want = 100;
}
task.tile_id = ptile->index;
client/gui-gtk-4.0/citydlg.c
if (act == ACTIVITY_LAST) {
task.tgt = -1;
task.want = 0;
task.wanted = 0;
} else {
enum extra_cause cause = activity_to_extra_cause(act);
enum extra_rmcause rmcause = activity_to_extra_rmcause(act);
......
}
task.tgt = -1;
task.wanted = 0;
} else {
task.tgt = extra_index(tgt);
switch (task.activity)
{
case ACTIVITY_CLEAN:
task.wanted = CITY_ACTIVITY_MEDIUM_WANTED;
break;
case ACTIVITY_CONVERT:
case ACTIVITY_CULTIVATE:
case ACTIVITY_PLANT:
case ACTIVITY_TRANSFORM:
task.wanted = CITY_ACTIVITY_MAX_WANTED;
break;
default:
task.wanted = CITY_ACTIVITY_DEFAULT_WANTED;
break;
}
}
task.want = 100;
}
task.tile_id = ptile->index;
client/gui-gtk-5.0/citydlg.c
if (act == ACTIVITY_LAST) {
task.tgt = -1;
task.want = 0;
task.wanted = 0;
} else {
enum extra_cause cause = activity_to_extra_cause(act);
enum extra_rmcause rmcause = activity_to_extra_rmcause(act);
......
}
task.tgt = -1;
task.wanted = 0;
} else {
task.tgt = extra_index(tgt);
switch (task.activity)
{
case ACTIVITY_CLEAN:
task.wanted = CITY_ACTIVITY_MEDIUM_WANTED;
break;
case ACTIVITY_CONVERT:
case ACTIVITY_CULTIVATE:
case ACTIVITY_PLANT:
case ACTIVITY_TRANSFORM:
task.wanted = CITY_ACTIVITY_MAX_WANTED;
break;
default:
task.wanted = CITY_ACTIVITY_DEFAULT_WANTED;
break;
}
}
task.want = 100;
}
task.tile_id = ptile->index;
client/gui-qt/citydlg.cpp
return;
}
task.want = 100;
if (target) {
enum extra_cause cause = activity_to_extra_cause(task.activity);
enum extra_rmcause rmcause = activity_to_extra_rmcause(task.activity);
......
if (tgt != nullptr) {
task.tgt = extra_index(tgt);
switch (task.activity)
{
case ACTIVITY_CLEAN:
task.wanted = CITY_ACTIVITY_MEDIUM_WANTED;
break;
case ACTIVITY_CONVERT:
case ACTIVITY_CULTIVATE:
case ACTIVITY_PLANT:
case ACTIVITY_TRANSFORM:
task.wanted = CITY_ACTIVITY_MAX_WANTED;
break;
default:
task.wanted = CITY_ACTIVITY_DEFAULT_WANTED;
break;
}
} else {
task.tgt = -1;
task.wanted = 0;
}
} else {
task.tgt = -1;
task.wanted = 0;
}
task.tile_id = ptile->index;
client/packhand.c
if (packet->activity == ACTIVITY_LAST) {
return;
} else {
ptask = fc_malloc(sizeof(struct worker_task));
worker_task_list_append(pcity->task_reqs, ptask);
ptask = worker_task_create(pcity->task_reqs, NULL, ACTIVITY_IDLE, nullptr, 0);
}
} else {
if (packet->activity == ACTIVITY_LAST) {
worker_task_list_remove(pcity->task_reqs, ptask);
free(ptask);
worker_task_destroy(pcity->task_reqs, ptask);
ptask = NULL;
}
}
......
} else {
ptask->tgt = NULL;
}
ptask->want = packet->want;
ptask->wanted = packet->wanted;
ptask->enroute = packet->enroute;
}
if (ptask && !worker_task_is_sane(ptask)) {
log_debug("Bad worker task");
worker_task_list_remove(pcity->task_reqs, ptask);
free(ptask);
worker_task_destroy(pcity->task_reqs, ptask);
ptask = NULL;
return;
}
......
if (tileset_map_topo_compatible(packet->topology_id,
tileset, &ts_topo) == TOPO_INCOMP_HARD) {
tileset_error(LOG_NORMAL, tileset_name_get(tileset),
tileset_error(LOG_DEBUG, tileset_name_get(tileset),
_("Map topology (%s) and tileset (%s) incompatible."),
describe_topology(packet->topology_id), describe_topology(ts_topo));
}
common/actions.c
The returned string is in statically allocated astring, and thus this
function is not thread-safe.
**************************************************************************/
static const char *action_prob_to_text(const struct act_prob prob)
const char *action_prob_to_text(const struct act_prob prob)
{
static struct astring chance = ASTRING_INIT;
common/actions.h
const char *action_id_name_translation(action_id act_id);
const char *action_get_ui_name_mnemonic(action_id act_id,
const char *mnemonic);
const char *action_prob_to_text(const struct act_prob prob);
const char *action_prepare_ui_name(action_id act_id, const char *mnemonic,
const struct act_prob prob,
const char *custom);
common/city.c
/* Get city tile information using the city tile coordinates. This is an
* [x][y] array of integer values corresponding to city_map_index. The
* coordinates x and y are in the range [0, CITY_MAP_MAX_SIZE] */
static int city_map_xy[CITY_MAP_MAX_SIZE][CITY_MAP_MAX_SIZE];
static int city_map_xy[CITY_MAP_UBER_SIZE][CITY_MAP_UBER_SIZE];
/* Number of tiles of a city; depends on the squared city radius */
static int city_map_numtiles[CITY_MAP_MAX_RADIUS_SQ + 1];
static int city_map_numtiles[CITY_MAP_UBER_RADIUS_SQ + 1];
/* Definitions and functions for the tile_cache */
struct tile_cache {
......
int city_tile_index, int city_radius_sq)
{
fc_assert_ret_val(city_radius_sq >= CITY_MAP_MIN_RADIUS_SQ, FALSE);
fc_assert_ret_val(city_radius_sq <= CITY_MAP_MAX_RADIUS_SQ, FALSE);
fc_assert_ret_val(city_radius_sq <= CITY_MAP_UBER_RADIUS_SQ, FALSE);
/* tile indices are sorted from smallest to largest city radius */
if (city_tile_index < 0
......
int city_radius_sq)
{
fc_assert_ret_val(city_radius_sq >= CITY_MAP_MIN_RADIUS_SQ, 0);
fc_assert_ret_val(city_radius_sq <= CITY_MAP_MAX_RADIUS_SQ, 0);
fc_assert_ret_val(city_radius_sq <= CITY_MAP_UBER_RADIUS_SQ, 0);
fc_assert_ret_val(is_valid_city_coords(city_radius_sq, city_map_x,
city_map_y), 0);
......
}
fc_assert_ret_val(city_radius_sq >= CITY_MAP_MIN_RADIUS_SQ, -1);
fc_assert_ret_val(city_radius_sq <= CITY_MAP_MAX_RADIUS_SQ, -1);
fc_assert_ret_val(city_radius_sq <= CITY_MAP_UBER_RADIUS_SQ, -1);
return city_map_numtiles[city_radius_sq];
}
......
void generate_city_map_indices(void)
{
int i, dx, dy, city_x, city_y, dist, city_count_tiles = 0;
struct iter_index city_map_index_tmp[CITY_MAP_MAX_SIZE
* CITY_MAP_MAX_SIZE];
struct iter_index city_map_index_tmp[CITY_MAP_UBER_SIZE
* CITY_MAP_UBER_SIZE];
/* initialise map information for each city radii */
for (i = 0; i <= CITY_MAP_MAX_RADIUS_SQ; i++) {
for (i = 0; i <= CITY_MAP_UBER_RADIUS_SQ; i++) {
city_map_numtiles[i] = 0; /* will be set below */
}
......
* we don't know the number of tiles within the city radius, so we need
* an temporary city_map_index array. Its content will be copied into
* the real array below. */
for (dx = -CITY_MAP_MAX_RADIUS; dx <= CITY_MAP_MAX_RADIUS; dx++) {
for (dy = -CITY_MAP_MAX_RADIUS; dy <= CITY_MAP_MAX_RADIUS; dy++) {
for (dx = -CITY_MAP_UBER_RADIUS; dx <= CITY_MAP_UBER_RADIUS; dx++) {
for (dy = -CITY_MAP_UBER_RADIUS; dy <= CITY_MAP_UBER_RADIUS; dy++) {
dist = map_vector_to_sq_distance(dx, dy);
if (dist <= CITY_MAP_MAX_RADIUS_SQ) {
if (dist <= CITY_MAP_UBER_RADIUS_SQ) {
city_map_index_tmp[city_count_tiles].dx = dx;
city_map_index_tmp[city_count_tiles].dy = dy;
city_map_index_tmp[city_count_tiles].dist = dist;
for (i = CITY_MAP_MAX_RADIUS_SQ; i >= 0; i--) {
for (i = CITY_MAP_UBER_RADIUS_SQ; i >= 0; i--) {
if (dist <= i) {
/* increase number of tiles within this squared city radius */
city_map_numtiles[i]++;
......
/* Free worker tasks */
while (worker_task_list_size(pcity->task_reqs) > 0) {
struct worker_task *ptask = worker_task_list_get(pcity->task_reqs, 0);
worker_task_list_remove(pcity->task_reqs, ptask);
free(ptask);
worker_task_destroy(pcity->task_reqs, ptask);
}
worker_task_list_destroy(pcity->task_reqs);
common/city.h
#include "specenum_gen.h"
/* The city includes all tiles dx^2 + dy^2 <= CITY_MAP_*_RADIUS_SQ */
#define CITY_MAP_DEFAULT_RADIUS_SQ \
(CITY_MAP_DEFAULT_RADIUS * CITY_MAP_DEFAULT_RADIUS + 1)
#define CITY_MAP_MIN_RADIUS_SQ \
(CITY_MAP_MIN_RADIUS * CITY_MAP_MIN_RADIUS + 1)
#define CITY_MAP_DEFAULT_RADIUS_SQ \
(CITY_MAP_DEFAULT_RADIUS * CITY_MAP_DEFAULT_RADIUS + 1)
#define CITY_MAP_LARGE_RADIUS_SQ \
(CITY_MAP_LARGE_RADIUS * CITY_MAP_LARGE_RADIUS + 1)
#define CITY_MAP_HUGE_RADIUS_SQ \
(CITY_MAP_HUGE_RADIUS * CITY_MAP_HUGE_RADIUS + 1)
#define CITY_MAP_MAX_RADIUS_SQ \
(CITY_MAP_MAX_RADIUS * CITY_MAP_MAX_RADIUS + 1)
#define CITY_MAP_UBER_RADIUS_SQ \
(CITY_MAP_UBER_RADIUS * CITY_MAP_UBER_RADIUS + 13)
/* The id for the city center */
#define CITY_MAP_CENTER_RADIUS_SQ -1
/* The tile index of the city center */
......
/* Maximum diameter of the workable city area. */
#define CITY_MAP_MAX_SIZE (CITY_MAP_MAX_RADIUS * 2 + 1)
#define CITY_MAP_UBER_SIZE (CITY_MAP_UBER_RADIUS * 2 + 1)
#define CITY_ACTIVITY_MIN_WANTED 1
#define CITY_ACTIVITY_DEFAULT_WANTED 5
#define CITY_ACTIVITY_MEDIUM_WANTED 9
#define CITY_ACTIVITY_MAX_WANTED 13
#define INCITE_IMPOSSIBLE_COST (1000 * 1000 * 1000)
common/fc_types.h
* in incompatible savefiles. */
#define CITY_MAP_MIN_RADIUS 0
#define CITY_MAP_DEFAULT_RADIUS 2
#define CITY_MAP_LARGE_RADIUS 3
#define CITY_MAP_HUGE_RADIUS 4
#define CITY_MAP_MAX_RADIUS 5
#define CITY_MAP_UBER_RADIUS (CITY_MAP_MAX_RADIUS + 1)
/* Below size of city tiles array is big enough for radius 5 city */
FC_STATIC_ASSERT(CITY_MAP_MAX_RADIUS <= 5, too_many_city_tiles);
common/unit.c
memset(punit->upkeep, 0, O_LAST * sizeof(*punit->upkeep));
punit->goto_tile = nullptr;
punit->worker_activity = ACTIVITY_IDLE;
punit->worker_target = NULL;
max_vet_lvl = utype_veteran_levels(punittype) - 1;
punit->veteran = MIN(veteran_level, max_vet_lvl);
/* A unit new and fresh ... */
......
punit->carrying = nullptr;
log_debug("unit_virtual_create set to IDLE - %s:%d", __FILE__, __LINE__);
set_unit_activity(punit, ACTIVITY_IDLE, ACTION_NONE);
punit->battlegroup = BATTLEGROUP_NONE;
punit->has_orders = FALSE;
......
{
if (punit->has_orders) {
punit->goto_tile = NULL;
punit->worker_activity = ACTIVITY_IDLE;
punit->worker_target = NULL;
free(punit->orders.list);
punit->orders.list = NULL;
}
common/unit.h
int veteran;
int fuel;
struct tile *goto_tile; /* May be NULL. */
enum unit_activity activity;
enum gen_action action;
struct tile *goto_tile; /* May be NULL. */
enum unit_activity worker_activity;
struct extra_type *worker_target; /* May be NULL */
/* The amount of work that has been done on the current activity. This
* is counted in turns but is multiplied by ACTIVITY_FACTOR (which allows
* fractional values in some cases). */
common/workertask.c
****************************************************************************/
void worker_task_init(struct worker_task *ptask)
{
ptask->act = ACTIVITY_IDLE;
ptask->ptile = NULL;
ptask->want = 0;
ptask->tgt = nullptr;
ptask->wanted = 0;
ptask->enroute = 0;
ptask->placed = 0;
}
/************************************************************************//**
.
****************************************************************************/
struct worker_task * worker_task_create(struct worker_task_list *task_reqs,
struct tile *ptile,
enum unit_activity act,
struct extra_type * target, int want)
{
struct worker_task *ptask = fc_malloc(sizeof(struct worker_task));
ptask->ptile = ptile;
ptask->act = act;
ptask->tgt = target;
ptask->wanted = want;
ptask->enroute = 0;
ptask->placed = 0;
worker_task_list_append(task_reqs, ptask);
return ptask;
}
/************************************************************************//**
.
****************************************************************************/
void worker_task_destroy(struct worker_task_list *task_reqs,
struct worker_task *ptask)
{
if (task_reqs != nullptr) worker_task_list_remove(task_reqs, ptask);
if (ptask != nullptr) free(ptask);
}
/************************************************************************//**
common/workertask.h
struct tile *ptile;
enum unit_activity act;
struct extra_type *tgt;
int want;
int wanted;
int enroute;
int placed;
};
/* get 'struct worker_task_list' and related functions: */
......
#define worker_task_list_iterate_end LIST_ITERATE_END
void worker_task_init(struct worker_task *ptask);
struct worker_task * worker_task_create(struct worker_task_list *task_reqs,
struct tile *ptile,
enum unit_activity act,
struct extra_type * target,
int want );
void worker_task_destroy(struct worker_task_list *task_reqs,
struct worker_task *ptask);
bool worker_task_is_sane(struct worker_task *ptask);
configure.ac
*) AC_MSG_ERROR([bad value ${enableval} for --with-qtver]) ;;
esac], [qt_ver="Qt6"])
AC_DEFINE([FREECIV_SVG_FLAGS], [1], [SVG flags features])
if test "x$qt_ver" = "xQt6x" ; then
AC_DEFINE([FC_QT6X_MODE], [1], [this is build based on current Qt6 version])
fi
server/actiontools.c
enum unit_activity activity = action_get_activity(paction);
unit_assign_specific_activity_target(actor_unit, &activity,
action_number(paction), &pextra);
action_number(paction), pextra);
if (pextra != NULL) {
return extra_number(pextra);
server/advisors/advgoto.c
enum unit_activity activity = punit->activity;
struct extra_type *tgt = punit->activity_target;
bool alive;
int unit_id = punit->id;
if (punit->moves_left <= 0) {
return TRUE;
......
punit->goto_tile = ptile;
unit_activity_handling(punit, ACTIVITY_GOTO, ACTION_NONE);
alive = adv_unit_execute_path(punit, path);
alive = adv_unit_execute_path(punit, path) && unit_is_alive(unit_id);
if (alive) {
if (activity != ACTIVITY_GOTO) {
/* Only go via ACTIVITY_IDLE if we are actually changing the activity */
unit_activity_handling(punit, ACTIVITY_IDLE, ACTION_NONE);
send_unit_info(NULL, punit); /* FIXME: probably duplicate */
unit_activity_handling_targeted(punit, activity, &tgt,
unit_activity_handling_targeted(punit, activity, tgt,
activity_default_action(activity));
}
punit->goto_tile = old_tile; /* May be NULL. */
......
} else {
(void) adv_unit_move(punit, ptile);
}
if (!game_unit_by_number(id)) {
/* Died... */
return FALSE;
}
if (!same_pos(unit_tile(punit), ptile) || punit->moves_left <= 0) {
/* Stopped (or maybe fought) or ran out of moves */
return TRUE;
}
// if (!same_pos(unit_tile(punit), ptile) || punit->moves_left <= 0) {
// /* Stopped (or maybe fought) or ran out of moves */
// return TRUE;
// }
}
return TRUE;
server/advisors/autoexplorer.c
* If we're a barbarian and the tile has a hut, don't go there. */
/* FIXME: Would be ok for a unit that does not enter or frighten hut */
if (is_barbarian(pplayer) && hut_on_tile(ptile)) {
UNIT_LOG(LOG_DEBUG, punit, "« barbarian avoiding huts");
return 0;
}
/* Do no try to cross borders and break a treaty, etc. */
if (!player_may_explore(ptile, punit->owner, unit_type_get(punit))) {
return 0;
if (!utype_has_flag(unit_type_get(punit), UTYF_CIVILIAN)
&& tile_non_allied_unit(ptile, pplayer,
unit_has_type_flag(punit, UTYF_FLAGLESS))) {
// exploring military should be interested, maybe attack!
desirable += HUT_SCORE;
UNIT_LOG(LOG_DEBUG, punit, "attack maybe (%d)", desirable);
} else {
UNIT_LOG(LOG_DEBUG, punit, "« don't break a treaty");
return 0;
}
}
circle_iterate(&(wld.map), ptile, radius_sq, ptile1) {
......
+ (100 - native) * KNOWN_DIFF_TER_SCORE);
}
}
UNIT_LOG(LOG_DEBUG, punit, "desirability (%d)", desirable);
} circle_iterate_end;
if (unknown <= 0) {
/* We make sure we'll uncover at least one unexplored tile. */
desirable = 0;
UNIT_LOG(LOG_DEBUG, punit, "not unknown reset (%d)", desirable);
}
if ((!is_ai(pplayer) || !has_handicap(pplayer, H_HUTS))
......
/* we want to explore huts whenever we can,
* even if doing so will not uncover any tiles. */
desirable += HUT_SCORE;
UNIT_LOG(LOG_DEBUG, punit, "hut boost (%d)", desirable);
}
UNIT_LOG(LOG_DEBUG, punit, "« desirability (%d)", desirable);
return desirable;
}
......
UNIT_LOG(LOG_DEBUG, punit, "auto-exploring.");
if (!is_human(pplayer) && unit_has_type_flag(punit, UTYF_GAMELOSS)) {
UNIT_LOG(LOG_DEBUG, punit, "exploration too dangerous!");
UNIT_LOG(LOG_DEBUG, punit, "(MR_BAD_ACTIVITY) — exploration too dangerous!");
return MR_BAD_ACTIVITY; /* too dangerous */
}
......
CALL_PLR_AI_FUNC(want_to_explore, pplayer, punit, best_tile, &allow);
}
if (allow == OVERRIDE_FALSE) {
UNIT_LOG(LOG_DEBUG, punit, "not allowed to explore");
UNIT_LOG(LOG_DEBUG, punit, "(MR_NOT_ALLOWED) — not allowed to explore");
return MR_NOT_ALLOWED;
}
if (!explorer_goto(punit, best_tile)) {
if (!utype_has_flag(unit_type_get(punit), UTYF_CIVILIAN)
&& tile_non_allied_unit(best_tile, pplayer,
unit_has_type_flag(punit, UTYF_FLAGLESS))) {
UNIT_LOG(LOG_DEBUG, punit, "(MR_DESTINATION_OCCUPIED_BY_NON_ALLIED_UNIT) — halt; other adjacent");
return MR_DESTINATION_OCCUPIED_BY_NON_ALLIED_UNIT;
} else if (!explorer_goto(punit, best_tile)) {
log_debug("(MR_DEATH) — unexpected un-aliving");
/* Died? Strange... */
return MR_DEATH;
}
......
UNIT_LOG(LOG_DEBUG, punit, "recursively exploring...");
return manage_auto_explorer(punit);
} else {
UNIT_LOG(LOG_DEBUG, punit, "done exploring (all finished)...");
UNIT_LOG(LOG_DEBUG, punit, "(MR_PAUSE) — done exploring (all finished)...");
return MR_PAUSE;
}
}
UNIT_LOG(LOG_DEBUG, punit, "done exploring (but more go go)...");
UNIT_LOG(LOG_DEBUG, punit, "(MR_OK) — done exploring (but more go go)...");
return MR_OK;
} else {
/* Didn't find anything. */
UNIT_LOG(LOG_DEBUG, punit, "failed to explore more");
UNIT_LOG(LOG_DEBUG, punit, "(MR_BAD_MAP_POSITION) ­— failed to explore more");
return MR_BAD_MAP_POSITION;
}
#undef DIST_FACTOR
server/advisors/autoworkers.c
/* server */
#include "citytools.h"
#include "cityturn.h"
#include "maphand.h"
#include "plrhand.h"
#include "srv_log.h"
......
i = 0;
action_array_add_all_by_result(aw_actions_rmextra, &i,
ACTRES_CLEAN);
action_array_add_all_by_result(aw_actions_rmextra, &i,
ACTRES_PILLAGE);
/* We could have ACTRES_PILLAGE here, but currently we don't */
action_array_end(aw_actions_rmextra, i);
}
......
return best_newv;
}
static struct extra_type *ecoal = NULL;
static struct extra_type *efallout = NULL;
static struct extra_type *efarmland = NULL;
static struct extra_type *efruit = NULL;
static struct extra_type *efurs = NULL;
static struct extra_type *egame = NULL;
static struct extra_type *egems = NULL;
static struct extra_type *eirrigation = NULL;
static struct extra_type *eivory = NULL;
static struct extra_type *emine = NULL;
static struct extra_type *eoasis = NULL;
static struct extra_type *eoil = NULL;
static struct extra_type *eoilwell = NULL;
static struct extra_type *epeat = NULL;
static struct extra_type *epollution = NULL;
static struct extra_type *erailroad = NULL;
static struct extra_type *eroad = NULL;
static struct extra_type *eruins = NULL;
static struct extra_type *esilk = NULL;
static struct extra_type *espice = NULL;
static struct extra_type *ewine = NULL;
static struct terrain *tdesert = NULL;
static struct terrain *tforest = NULL;
static struct terrain *tglacier = NULL;
static struct terrain *thills = NULL;
static struct terrain *tjungle = NULL;
static struct terrain *tmountains = NULL;
static struct terrain *tswamp = NULL;
static struct terrain *ttundra = NULL;
static struct cm_parameter cmp;
static struct tile *request_compare_tile = NULL; //! NOT thread safe
/**********************************************************************//**
.
**************************************************************************/
int city_proximity_compare(const struct city *const *left,
const struct city *const *right)
{
if (request_compare_tile == NULL) return 0;
int left_dist = map_distance(request_compare_tile, city_tile(*left));
int right_dist = map_distance(request_compare_tile, city_tile(*right));
if (left_dist == right_dist) return 0;
if (left_dist < right_dist) return -1;
return 1;
}
/**********************************************************************//**
.
**************************************************************************/
int worker_tasks_compare(const struct worker_task *const *left,
const struct worker_task *const *right)
{
if (request_compare_tile == NULL) return 0;
int left_dist = map_distance(request_compare_tile, (*left)->ptile);
int right_dist = map_distance(request_compare_tile, (*right)->ptile);
if (left_dist == right_dist) return 0;
if (left_dist < right_dist) return -1;
return 1;
}
struct unreachable
{
struct city *pcity;
struct worker_task *ptask;
};
#define SPECLIST_TAG unreachable
#define SPECLIST_TYPE struct unreachable
#include "speclist.h"
#define unreachable_list_iterate(tasklist, ptask) \
TYPED_LIST_ITERATE(struct unreachable, tasklist, ptask)
#define unreachable_list_iterate_end LIST_ITERATE_END
/************************************************************************//**
.
****************************************************************************/
void unreachable_create(struct unreachable_list *unreachables,
struct city *pcity,
struct worker_task *ptask)
{
struct unreachable *punreachable = fc_malloc(sizeof(struct unreachable));
punreachable->pcity = pcity;
punreachable->ptask = ptask;
unreachable_list_append(unreachables, punreachable);
}
/************************************************************************//**
.
****************************************************************************/
void unreachable_destroy(struct unreachable_list *unreachables,
struct unreachable *punreachable)
{
if (unreachables != nullptr) unreachable_list_remove(unreachables,
punreachable);
if (punreachable != nullptr) free(punreachable);
}
/**********************************************************************//**
Return best city request to fulfill.
**************************************************************************/
struct city *worker_evaluate_city_requests(struct unit *punit,
struct worker_task **best_task,
void worker_evaluate_city_requests(struct unit *punit,
struct pf_path **ppath,
struct workermap *state)
{
......
struct pf_parameter parameter;
struct pf_map *pfm;
struct pf_position pos;
int best_value = -1;
struct worker_task *best = NULL;
struct city *taskcity = NULL;
int dist = FC_INFINITY;
const struct civ_map *nmap = &(wld.map);
pft_fill_unit_parameter(&parameter, nmap, punit);
parameter.omniscience = !has_handicap(pplayer, H_MAP);
parameter.get_TB = autoworker_tile_behavior;
if (punit->worker_activity != ACTIVITY_IDLE) {
if (punit->goto_tile == nullptr || punit->worker_activity == ACTIVITY_LAST) {
UNIT_LOG(LOG_DEBUG, punit, "%s \x1b[33m%s\x1b[0m",
unit_activity_name(punit->worker_activity),
(punit->worker_activity == ACTIVITY_LAST) ? "confused" : "lost");
punit->worker_activity = ACTIVITY_IDLE;
punit->worker_target = nullptr;
punit->goto_tile = nullptr;
unit_activity_handling(punit, ACTIVITY_IDLE,
activity_default_action(ACTIVITY_IDLE));
send_unit_info(NULL, punit); /* FIXME: Probably duplicate */
} else if (same_pos(unit_tile(punit), punit->goto_tile)) {
if (punit->worker_activity == ACTIVITY_TRANSFORM
&& tdesert != tile_terrain(unit_tile(punit))
&& tglacier != tile_terrain(unit_tile(punit))
&& tswamp != tile_terrain(unit_tile(punit))
&& ttundra != tile_terrain(unit_tile(punit))) {
UNIT_LOG(LOG_DEBUG, punit, "%s \x1b[33mretracted\x1b[0m (wrong terrain)",
unit_activity_name(punit->worker_activity));
punit->worker_activity = ACTIVITY_IDLE;
punit->worker_target = nullptr;
punit->goto_tile = nullptr;
unit_activity_handling(punit, ACTIVITY_IDLE,
activity_default_action(ACTIVITY_IDLE));
send_unit_info(NULL, punit); /* FIXME: Probably duplicate */
} else if (auto_workers_speculate_can_act_at(punit,
punit->worker_activity,
parameter.omniscience,
punit->worker_target,
unit_tile(punit))) {
if (activity_requires_target(punit->worker_activity)) {
unit_activity_handling_targeted(punit, punit->worker_activity,
punit->worker_target,
activity_default_action(punit->worker_activity));
} else {
unit_activity_handling(punit, punit->worker_activity,
activity_default_action(punit->worker_activity));
}
send_unit_info(NULL, punit); /* FIXME: Probably duplicate */
UNIT_LOG(LOG_DEBUG, punit, "already at worksite — starting work");
} else {
punit->worker_activity = ACTIVITY_IDLE;
punit->worker_target = nullptr;
punit->goto_tile = nullptr;
unit_activity_handling(punit, ACTIVITY_IDLE,
activity_default_action(ACTIVITY_IDLE));
send_unit_info(NULL, punit); /* FIXME: Probably duplicate */
UNIT_LOG(LOG_DEBUG, punit, "reached its worksite \x1b[33munworkable\x1b[0m");
}
}
if (punit->worker_activity != ACTIVITY_IDLE) {
UNIT_LOG(LOG_DEBUG, punit, "\x1b[32m%s\x1b[0m",
unit_activity_name(punit->worker_activity));
return;
}
} else if (punit->goto_tile != nullptr && punit->moves_left > 0) {
UNIT_LOG(LOG_DEBUG, punit, "\x1b[32mpossible stalled goto\x1b[0m");
}
if (tjungle == NULL) {
ecoal = extra_type_by_rule_name(_("Coal"));
efallout = extra_type_by_rule_name(_("Fallout"));
efarmland = extra_type_by_rule_name(_("Farmland"));
efruit = extra_type_by_rule_name(_("Fruit"));
efurs = extra_type_by_rule_name(_("Furs"));
egame = extra_type_by_rule_name(_("?animals:Game"));
egems = extra_type_by_rule_name(_("Gems"));
eirrigation = extra_type_by_rule_name(_("Irrigation"));
eivory = extra_type_by_rule_name(_("Ivory"));
emine = extra_type_by_rule_name(_("?extra:Mine"));
eoasis = extra_type_by_rule_name(_("Oasis"));
eoil = extra_type_by_rule_name(_("Oil"));
eoilwell = extra_type_by_rule_name(_("Oil Well"));
epeat = extra_type_by_rule_name(_("Peat"));
epollution = extra_type_by_rule_name(_("?extra:Pollution"));
erailroad = extra_type_by_rule_name(_("Railroad"));
eroad = extra_type_by_rule_name(_("Road"));
eruins = extra_type_by_rule_name(_("Ruins"));
esilk = extra_type_by_rule_name(_("Silk"));
espice = extra_type_by_rule_name(_("Spice"));
ewine = extra_type_by_rule_name(_("Wine"));
tdesert = terrain_by_rule_name(_("Desert"));
tforest = terrain_by_rule_name(_("Forest"));
tglacier = terrain_by_rule_name(_("Glacier"));
thills = terrain_by_rule_name(_("Hills"));
tjungle = terrain_by_rule_name(_("Jungle"));
tmountains = terrain_by_rule_name(_("Mountains"));
tswamp = terrain_by_rule_name(_("Swamp"));
ttundra = terrain_by_rule_name(_("Tundra"));
cm_init_parameter(&cmp);
}
pfm = pf_map_new(&parameter);
/* Have nearby cities requests? */
city_list_iterate(pplayer->cities, pcity) {
struct tile *utile = unit_tile(punit);
struct city_list *unit_cities = city_list_new();
city_tile_iterate(nmap, CITY_MAP_UBER_RADIUS_SQ, utile, ptile) {
if (is_allied_city_tile(ptile, unit_owner(punit))) {
city_list_append(unit_cities, tile_city(ptile));
}
} city_tile_iterate_end;
request_compare_tile = unit_tile(punit);
city_list_sort(unit_cities, city_proximity_compare);
city_list_iterate(unit_cities, pcity) {
int tasks_appended = 0;
struct tile *acenter = city_tile(pcity);
int city_radius_sq = city_map_radius_sq_get(pcity);
int city_radius_sq_plus = 10; //game.info.init_city_radius_sq
//+ get_city_bonus(pcity, EFT_CITY_RADIUS_SQ);
struct cm_parameter *pcmp;
struct unreachable_list *unreachables = unreachable_list_new();
CITY_LOG(LOG_DEBUG, pcity, "(%d) tasks in queue: %d", city_radius_sq,
worker_task_list_size(pcity->task_reqs));
if (pcity->cm_parameter) {
pcmp = pcity->cm_parameter;
} else {
pcmp = &cmp;
set_default_city_manager(&cmp, pcity);
}
switch (city_radius_sq) {
case CITY_MAP_MIN_RADIUS_SQ:
city_radius_sq_plus = CITY_MAP_DEFAULT_RADIUS_SQ;
break;
case CITY_MAP_DEFAULT_RADIUS_SQ:
city_radius_sq_plus = CITY_MAP_LARGE_RADIUS_SQ;
break;
case CITY_MAP_LARGE_RADIUS_SQ:
city_radius_sq_plus = CITY_MAP_HUGE_RADIUS_SQ;
break;
case CITY_MAP_HUGE_RADIUS_SQ:
city_radius_sq_plus = CITY_MAP_MAX_RADIUS_SQ;
break;
case CITY_MAP_MAX_RADIUS_SQ:
city_radius_sq_plus = CITY_MAP_UBER_RADIUS_SQ;
break;
default:
fc_assert_exit_msg(FALSE, "unhandled city_radius_sq (%d) in %s:%d",
city_radius_sq, __FILE__, __LINE__);
break;
}
city_tile_iterate(nmap, city_radius_sq, acenter, ptile) {
bool clean_tasked = false;
bool pillage_tasked = false;
if (tile_has_extra(ptile, epollution)
|| tile_has_extra(ptile, efallout)
|| tile_has_extra(ptile, eruins)) {
worker_task_list_iterate(pcity->task_reqs, ptask) {
bool consider = TRUE;
if (ptask->ptile == ptile) {
if (ptask->act == ACTIVITY_CLEAN) clean_tasked = true;
if (ptask->act == ACTIVITY_PILLAGE) pillage_tasked = true;
if (clean_tasked && pillage_tasked) break;
}
} worker_task_list_iterate_end;
if (!clean_tasked) {
if (tile_has_extra(ptile, epollution)) {
worker_task_create(pcity->task_reqs, ptile, ACTIVITY_CLEAN,
epollution, CITY_ACTIVITY_MAX_WANTED);
++tasks_appended;
log_debug("%s(%d, %d) « %s", terrain_rule_name(ptile->terrain),
TILE_XY(ptile), unit_activity_name(ACTIVITY_CLEAN));
}
if (tile_has_extra(ptile, efallout)) {
worker_task_create(pcity->task_reqs, ptile, ACTIVITY_CLEAN,
efallout, CITY_ACTIVITY_MAX_WANTED);
++tasks_appended;
log_debug("%s(%d, %d) « %s", terrain_rule_name(ptile->terrain),
TILE_XY(ptile), unit_activity_name(ACTIVITY_CLEAN));
}
}
/* Do not go to tiles that already have workers there. */
if (!pillage_tasked) {
if (tile_has_extra(ptile, eruins)) {
worker_task_create(pcity->task_reqs, ptile, ACTIVITY_PILLAGE,
eruins, CITY_ACTIVITY_MIN_WANTED);
++tasks_appended;
log_debug("%s(%d, %d) « %s", terrain_rule_name(ptile->terrain),
TILE_XY(ptile), unit_activity_name(ACTIVITY_PILLAGE));
}
}
}
} city_tile_iterate_end;
if (worker_task_list_size(pcity->task_reqs) <= tasks_appended) {
CITY_LOG(LOG_DEBUG, pcity, "size %d, radius_sq %d (%d)",
city_size_get(pcity), city_radius_sq, city_radius_sq_plus);
city_tile_iterate(nmap, city_radius_sq_plus, acenter, ptile) {
if (!is_ocean_tile(ptile)) {
struct extra_type *tgt = eroad;
struct road_type *proad = extra_road_get(tgt);
if (!road_can_be_built(proad, ptile)) {
tgt = erailroad;
proad = extra_road_get(tgt);
}
if (road_can_be_built(proad, ptile)) {
worker_task_create(pcity->task_reqs, ptile, ACTIVITY_GEN_ROAD, tgt,
CITY_ACTIVITY_DEFAULT_WANTED);
++tasks_appended;
log_debug("%s(%d, %d) « %s", terrain_rule_name(ptile->terrain),
TILE_XY(ptile), unit_activity_name(ACTIVITY_GEN_ROAD));
}
}
} city_tile_iterate_end;
city_tile_iterate(nmap, city_radius_sq, acenter, ptile) {
if (!is_ocean_tile(ptile)
&& tforest != tile_terrain(ptile)
&& tmountains != tile_terrain(ptile)
&& tglacier != tile_terrain(ptile)
&& ttundra != tile_terrain(ptile)
&& tjungle != tile_terrain(ptile)
&& !tile_has_extra(ptile, ecoal)
&& !tile_has_extra(ptile, eoil)) {
enum unit_activity act = ACTIVITY_IRRIGATE;
struct extra_type *tgt = eirrigation;
if (thills == tile_terrain(ptile)
&& (pcmp->factor[O_SHIELD] > pcmp->factor[O_FOOD]
|| (pcmp->factor[O_SHIELD] == pcmp->factor[O_FOOD]
... This diff was truncated because it exceeds the maximum size that can be displayed.
(1-1/3)