Feature #1375 » main-superspecialists-basic.patch
ai/default/daieffects.c | ||
---|---|---|
{
|
||
int providers = 0;
|
||
specialist_type_iterate(i) {
|
||
normal_specialist_type_iterate(i) {
|
||
if (get_specialist_output(pcity, i, O_LUXURY) >= game.info.happy_cost) {
|
||
providers += pcity->specialists[i];
|
||
}
|
||
} specialist_type_iterate_end;
|
||
} normal_specialist_type_iterate_end;
|
||
return providers;
|
||
}
|
ai/default/daimilitary.c | ||
---|---|---|
}
|
||
if (!martial_need) {
|
||
specialist_type_iterate(sp) {
|
||
normal_specialist_type_iterate(sp) {
|
||
if (pcity->specialists[sp] > 0
|
||
&& get_specialist_output(pcity, sp, O_LUXURY) > 0) {
|
||
martial_need = TRUE;
|
||
break;
|
||
}
|
||
} specialist_type_iterate_end;
|
||
} normal_specialist_type_iterate_end;
|
||
}
|
||
if (martial_need
|
ai/default/daiunit.c | ||
---|---|---|
int entertainers = 0;
|
||
bool enough = FALSE;
|
||
specialist_type_iterate(sp) {
|
||
normal_specialist_type_iterate(sp) {
|
||
if (get_specialist_output(pcity, sp, O_LUXURY) > 0) {
|
||
entertainers += pcity->specialists[sp];
|
||
}
|
||
} specialist_type_iterate_end;
|
||
} normal_specialist_type_iterate_end;
|
||
martless_unhappy += entertainers; /* We want to use martial law instead
|
||
* of entertainers. */
|
client/agents/cma_core.c | ||
---|---|---|
T(disorder);
|
||
T(happy);
|
||
specialist_type_iterate(sp) {
|
||
normal_specialist_type_iterate(sp) {
|
||
T(specialists[sp]);
|
||
} specialist_type_iterate_end;
|
||
} normal_specialist_type_iterate_end;
|
||
output_type_iterate(ot) {
|
||
T(surplus[ot]);
|
||
... | ... | |
} city_tile_iterate_skip_free_worked_end;
|
||
/* Change the excess non-default specialists to default. */
|
||
specialist_type_iterate(sp) {
|
||
normal_specialist_type_iterate(sp) {
|
||
int i;
|
||
if (sp == DEFAULT_SPECIALIST) {
|
||
... | ... | |
first_request_id = last_request_id;
|
||
}
|
||
}
|
||
} specialist_type_iterate_end;
|
||
} normal_specialist_type_iterate_end;
|
||
/* now all surplus people are DEFAULT_SPECIALIST */
|
||
... | ... | |
/* Set all specialists except DEFAULT_SPECIALIST (all the unchanged
|
||
* ones remain as DEFAULT_SPECIALIST). */
|
||
specialist_type_iterate(sp) {
|
||
normal_specialist_type_iterate(sp) {
|
||
int i;
|
||
if (sp == DEFAULT_SPECIALIST) {
|
||
... | ... | |
first_request_id = last_request_id;
|
||
}
|
||
}
|
||
} specialist_type_iterate_end;
|
||
} normal_specialist_type_iterate_end;
|
||
if (last_request_id == 0 || ALWAYS_APPLY_AT_SERVER) {
|
||
/*
|
client/citydlg_common.c | ||
---|---|---|
}
|
||
/**********************************************************************//**
|
||
Provide a list of all citizens in the city, in order. "index"
|
||
Provide a list of all citizens in the city, in order. "idx"
|
||
should be the happiness index (currently [0..4]; 4 = final
|
||
happiness). "citizens" should be an array large enough to hold all
|
||
happiness). "categories" should be an array large enough to hold all
|
||
citizens (use MAX_CITY_SIZE to be on the safe side).
|
||
Note that superspecialists are not included. There can be theoretically
|
||
times more superspecialists working than MAX_CITY_SIZE.
|
||
Returns size of the list.
|
||
**************************************************************************/
|
||
int get_city_citizen_types(struct city *pcity, enum citizen_feeling idx,
|
||
enum citizen_category *categories)
|
||
... | ... | |
categories[i] = CITIZEN_ANGRY;
|
||
}
|
||
specialist_type_iterate(sp) {
|
||
normal_specialist_type_iterate(sp) {
|
||
for (n = 0; n < pcity->specialists[sp]; n++, i++) {
|
||
categories[i] = CITIZEN_SPECIALIST + sp;
|
||
}
|
||
} specialist_type_iterate_end;
|
||
} normal_specialist_type_iterate_end;
|
||
if (city_size_get(pcity) != i) {
|
||
log_error("get_city_citizen_types() %d citizens "
|
||
... | ... | |
return i;
|
||
}
|
||
/**********************************************************************//**
|
||
Tries to fill city superspecialists into categories[cat_len] array.
|
||
If succeeds, returns how many are filled.
|
||
If there are too many of them, fills as many as fits and returns -1.
|
||
**************************************************************************/
|
||
int city_try_fill_superspecialists(struct city *pcity, int cat_len,
|
||
enum citizen_category *categories)
|
||
{
|
||
int i = 0, n;
|
||
super_specialist_type_iterate(sp) {
|
||
for (n = 0; n < pcity->specialists[sp]; n++, i++) {
|
||
if (i >= cat_len) {
|
||
return -1;
|
||
}
|
||
categories[i] = CITIZEN_SPECIALIST + sp;
|
||
}
|
||
} super_specialist_type_iterate_end;
|
||
return i;
|
||
}
|
||
/**********************************************************************//**
|
||
Rotate the given specialist citizen to the next type of citizen.
|
||
**************************************************************************/
|
||
... | ... | |
/* Loop through all specialists in order until we find a usable one
|
||
* (or run out of choices). */
|
||
to = from;
|
||
fc_assert(to >= 0 && to < specialist_count());
|
||
fc_assert(is_normal_specialist_id(to));
|
||
do {
|
||
to = (to + 1) % specialist_count();
|
||
to = (to + 1) % normal_specialist_count();
|
||
} while (to != from && !city_can_use_specialist(pcity, to));
|
||
if (from != to) {
|
client/citydlg_common.h | ||
---|---|---|
int get_city_citizen_types(struct city *pcity, enum citizen_feeling index,
|
||
enum citizen_category *categories);
|
||
int city_try_fill_superspecialists(struct city *pcity, int cat_len,
|
||
enum citizen_category *categories);
|
||
void city_rotate_specialist(struct city *pcity, int citizen_index);
|
||
void activate_all_units(struct tile *ptile);
|
client/gui-gtk-3.22/citydlg.c | ||
---|---|---|
int citizen_bar_width, citizen_bar_height;
|
||
struct city *pcity = pdialog->pcity;
|
||
int num_citizens = get_city_citizen_types(pcity, FEELING_FINAL, categories);
|
||
int num_supers
|
||
= city_try_fill_superspecialists(pcity,
|
||
ARRAY_SIZE(categories) - num_citizens,
|
||
&categories[num_citizens]);
|
||
cairo_t *cr;
|
||
if (num_supers >= 0) {
|
||
/* Just draw superspecalists in the common roster */
|
||
num_citizens += num_supers;
|
||
} else {
|
||
/* FIXME: show them in some compact way */
|
||
num_citizens = ARRAY_SIZE(categories);
|
||
}
|
||
/* If there is not enough space we stack the icons. We draw from left to */
|
||
/* right. width is how far we go to the right for each drawn pixmap. The */
|
||
/* last icon is always drawn in full, and so has reserved */
|
||
... | ... | |
struct city *pcity = pdialog->pcity;
|
||
int granaryturns;
|
||
int non_workers = city_specialists(pcity);
|
||
int supers = city_superspecialists(pcity);
|
||
/* fill the buffers with the necessary info */
|
||
if (non_workers) {
|
||
if (supers) {
|
||
fc_snprintf(buf[INFO_SIZE], sizeof(buf[INFO_SIZE]), "%3d (%3d+%d)",
|
||
pcity->size, non_workers, supers);
|
||
} else if (non_workers) {
|
||
fc_snprintf(buf[INFO_SIZE], sizeof(buf[INFO_SIZE]), "%3d (%3d)",
|
||
pcity->size, non_workers);
|
||
} else {
|
client/gui-gtk-4.0/citydlg.c | ||
---|---|---|
int citizen_bar_width, citizen_bar_height;
|
||
struct city *pcity = pdialog->pcity;
|
||
int num_citizens = get_city_citizen_types(pcity, FEELING_FINAL, categories);
|
||
int num_supers
|
||
= city_try_fill_superspecialists(pcity,
|
||
ARRAY_SIZE(categories) - num_citizens,
|
||
&categories[num_citizens]);
|
||
cairo_t *cr;
|
||
if (num_supers >= 0) {
|
||
/* Just draw superspecalists in the common roster */
|
||
num_citizens += num_supers;
|
||
} else {
|
||
/* FIXME: show them in some compact way */
|
||
num_citizens = ARRAY_SIZE(categories);
|
||
}
|
||
/* If there is not enough space we stack the icons. We draw from left to */
|
||
/* right. width is how far we go to the right for each drawn pixmap. The */
|
||
/* last icon is always drawn in full, and so has reserved */
|
||
... | ... | |
struct city *pcity = pdialog->pcity;
|
||
int granaryturns;
|
||
int non_workers = city_specialists(pcity);
|
||
int supers = city_superspecialists(pcity);
|
||
/* fill the buffers with the necessary info */
|
||
if (non_workers) {
|
||
if (supers) {
|
||
fc_snprintf(buf[INFO_SIZE], sizeof(buf[INFO_SIZE]), "%3d (%3d+%d)",
|
||
pcity->size, non_workers, supers);
|
||
} else if (non_workers) {
|
||
fc_snprintf(buf[INFO_SIZE], sizeof(buf[INFO_SIZE]), "%3d (%3d)",
|
||
pcity->size, non_workers);
|
||
} else {
|
client/gui-gtk-5.0/citydlg.c | ||
---|---|---|
int citizen_bar_width, citizen_bar_height;
|
||
struct city *pcity = pdialog->pcity;
|
||
int num_citizens = get_city_citizen_types(pcity, FEELING_FINAL, categories);
|
||
int num_supers
|
||
= city_try_fill_superspecialists(pcity,
|
||
ARRAY_SIZE(categories) - num_citizens,
|
||
&categories[num_citizens]);
|
||
cairo_t *cr;
|
||
if (num_supers >= 0) {
|
||
/* Just draw superspecalists in the common roster */
|
||
num_citizens += num_supers;
|
||
} else {
|
||
/* FIXME: show them in some compact way */
|
||
num_citizens = ARRAY_SIZE(categories);
|
||
}
|
||
/* If there is not enough space we stack the icons. We draw from left to */
|
||
/* right. width is how far we go to the right for each drawn pixmap. The */
|
||
/* last icon is always drawn in full, and so has reserved */
|
||
... | ... | |
struct city *pcity = pdialog->pcity;
|
||
int granaryturns;
|
||
int non_workers = city_specialists(pcity);
|
||
int supers = city_superspecialists(pcity);
|
||
/* fill the buffers with the necessary info */
|
||
if (non_workers) {
|
||
if (supers) {
|
||
fc_snprintf(buf[INFO_SIZE], sizeof(buf[INFO_SIZE]), "%3d (%3d+%d)",
|
||
pcity->size, non_workers, supers);
|
||
} else if (non_workers) {
|
||
fc_snprintf(buf[INFO_SIZE], sizeof(buf[INFO_SIZE]), "%3d (%3d)",
|
||
pcity->size, non_workers);
|
||
} else {
|
client/gui-qt/citydlg.cpp | ||
---|---|---|
QPainter p;
|
||
QPixmap *pix;
|
||
int num_citizens = get_city_citizen_types(dlgcity, FEELING_FINAL, categories);
|
||
int num_supers
|
||
= city_try_fill_superspecialists(pcity,
|
||
ARRAY_SIZE(categories) - num_citizens,
|
||
&categories[num_citizens]);
|
||
int w = tileset_small_sprite_width(tileset) / gui()->map_scale;
|
||
int h = tileset_small_sprite_height(tileset) / gui()->map_scale;
|
||
if (num_supers >= 0) {
|
||
/* Just draw superspecalists in the common roster */
|
||
num_citizens += num_supers;
|
||
} else {
|
||
/* FIXME: show them in some compact way */
|
||
num_citizens = ARRAY_SIZE(categories);
|
||
}
|
||
i = 1 + (num_citizens * 5 / 200);
|
||
w = w / i;
|
||
QRect source_rect(0, 0, w, h);
|
||
... | ... | |
char buf_info[NUM_INFO_FIELDS][512];
|
||
char buf_tooltip[NUM_INFO_FIELDS][512];
|
||
int granaryturns;
|
||
int spec;
|
||
int spec, supers;
|
||
for (int i = 0; i < NUM_INFO_FIELDS; i++) {
|
||
buf_info[i][0] = '\0';
|
||
... | ... | |
// Fill the buffers with the necessary info
|
||
spec = city_specialists(dlgcity);
|
||
supers = city_superspecialists(dlgcity);
|
||
fc_snprintf(buf_info[INFO_CITIZEN], sizeof(buf_info[INFO_CITIZEN]),
|
||
"%3d (%4d)", dlgcity->size, spec);
|
||
fc_snprintf(buf_tooltip[INFO_CITIZEN], sizeof(buf_tooltip[INFO_CITIZEN]),
|
||
_("Population: %d, Specialists: %d"),
|
||
dlgcity->size, spec);
|
||
if (supers) {
|
||
fc_snprintf(buf_tooltip[INFO_CITIZEN], sizeof(buf_tooltip[INFO_CITIZEN]),
|
||
_("Population: %d, Specialists: %d + %d"),
|
||
dlgcity->size, spec, supers);
|
||
} else {
|
||
fc_snprintf(buf_tooltip[INFO_CITIZEN], sizeof(buf_tooltip[INFO_CITIZEN]),
|
||
_("Population: %d, Specialists: %d"),
|
||
dlgcity->size, spec);
|
||
}
|
||
fc_snprintf(buf_info[INFO_FOOD], sizeof(buf_info[INFO_FOOD]), "%3d (%+4d)",
|
||
dlgcity->prod[O_FOOD], dlgcity->surplus[O_FOOD]);
|
||
fc_snprintf(buf_info[INFO_SHIELD], sizeof(buf_info[INFO_SHIELD]),
|
client/gui-sdl2/citydlg.c | ||
---|---|---|
/* count != 0 */
|
||
/* ==================================================== */
|
||
/* Draw Citizens */
|
||
/* Draw Citizens and Superspecialists*/
|
||
count = (pcity->feel[CITIZEN_HAPPY][FEELING_FINAL] + pcity->feel[CITIZEN_CONTENT][FEELING_FINAL]
|
||
+ pcity->feel[CITIZEN_UNHAPPY][FEELING_FINAL] + pcity->feel[CITIZEN_ANGRY][FEELING_FINAL]
|
||
+ city_specialists(pcity));
|
||
+ city_specialists(pcity) + city_superspecialists(pcity));
|
||
buf = get_citizen_surface(CITIZEN_HAPPY, 0);
|
||
client/gui-sdl3/citydlg.c | ||
---|---|---|
/* count != 0 */
|
||
/* ==================================================== */
|
||
/* Draw Citizens */
|
||
/* Draw Citizens and Superspecialists*/
|
||
count = (pcity->feel[CITIZEN_HAPPY][FEELING_FINAL] + pcity->feel[CITIZEN_CONTENT][FEELING_FINAL]
|
||
+ pcity->feel[CITIZEN_UNHAPPY][FEELING_FINAL] + pcity->feel[CITIZEN_ANGRY][FEELING_FINAL]
|
||
+ city_specialists(pcity));
|
||
+ city_specialists(pcity) + city_superspecialists(pcity));
|
||
buf = get_citizen_surface(CITIZEN_HAPPY, 0);
|
||
client/helpdata.c | ||
---|---|---|
cat_snprintf(buf, bufsz, "%s\n\n", _(text));
|
||
} strvec_iterate_end;
|
||
}
|
||
if (is_super_specialist(pspec)) {
|
||
cat_snprintf(buf, bufsz,
|
||
_("Superspecialist: is not counted within city population,"
|
||
"\ncan not be assigned to or from another occupation.\n"));
|
||
}
|
||
/* Requirements for this specialist. */
|
||
requirement_vector_iterate(&pspec->reqs, preq) {
|
client/packhand.c | ||
---|---|---|
}
|
||
specialist_type_iterate(sp) {
|
||
pcity->specialists[sp] = packet->specialists[sp];
|
||
city_size_add(pcity, pcity->specialists[sp]);
|
||
if (is_normal_specialist_id(sp)) {
|
||
city_size_add(pcity, pcity->specialists[sp]);
|
||
}
|
||
} specialist_type_iterate_end;
|
||
if (city_size_get(pcity) != packet->size) {
|
common/aicore/cm.c | ||
---|---|---|
fc_assert_ret(0 == soln->idle);
|
||
/* Clear all specialists, and remove all workers from fields (except
|
||
* the city center). */
|
||
memset(&pcity->specialists, 0, sizeof(pcity->specialists));
|
||
* the city center). Don't touch superspecialists. */
|
||
memset(&pcity->specialists, 0,
|
||
sizeof(pcity->specialists[0]) * normal_specialist_count());
|
||
city_map_iterate(city_radius_sq, cindex, x, y) {
|
||
if (is_free_worked_index(cindex)) {
|
||
... | ... | |
/* for each specialist type, create a tile_type that has as production
|
||
* the bonus for the specialist (if the city is allowed to use it) */
|
||
specialist_type_iterate(i) {
|
||
normal_specialist_type_iterate(i) {
|
||
if (city_can_use_specialist(pcity, i)) {
|
||
type.spec = i;
|
||
output_type_iterate(output) {
|
||
... | ... | |
tile_type_lattice_add(lattice, &type, 0);
|
||
}
|
||
} specialist_type_iterate_end;
|
||
} normal_specialist_type_iterate_end;
|
||
}
|
||
/************************************************************************//**
|
||
... | ... | |
{
|
||
int count = 0;
|
||
specialist_type_iterate(spec) {
|
||
normal_specialist_type_iterate(spec) {
|
||
count += result->specialists[spec];
|
||
} specialist_type_iterate_end;
|
||
} normal_specialist_type_iterate_end;
|
||
return count;
|
||
}
|
common/city.c | ||
---|---|---|
}
|
||
/**********************************************************************//**
|
||
Give the number of specialists in a city.
|
||
Give the number of citizens who are specialists in a city.
|
||
Does not count superspecialists
|
||
**************************************************************************/
|
||
citizens city_specialists(const struct city *pcity)
|
||
{
|
||
citizens count = 0;
|
||
specialist_type_iterate(sp) {
|
||
normal_specialist_type_iterate(sp) {
|
||
fc_assert_ret_val(MAX_CITY_SIZE - count > pcity->specialists[sp], 0);
|
||
count += pcity->specialists[sp];
|
||
} specialist_type_iterate_end;
|
||
} normal_specialist_type_iterate_end;
|
||
return count;
|
||
}
|
||
/**********************************************************************//**
|
||
Give the number of superspecialists in a city
|
||
**************************************************************************/
|
||
int city_superspecialists(const struct city *pcity)
|
||
{
|
||
int count = 0;
|
||
super_specialist_type_iterate(sp) {
|
||
count += pcity->specialists[sp];
|
||
} super_specialist_type_iterate_end;
|
||
return count;
|
||
}
|
||
... | ... | |
int best = DEFAULT_SPECIALIST;
|
||
int val = get_specialist_output(pcity, best, otype);
|
||
specialist_type_iterate(i) {
|
||
normal_specialist_type_iterate(i) {
|
||
if (!pcity || city_can_use_specialist(pcity, i)) {
|
||
int val2 = get_specialist_output(pcity, i, otype);
|
||
... | ... | |
val = val2;
|
||
}
|
||
}
|
||
} specialist_type_iterate_end;
|
||
} normal_specialist_type_iterate_end;
|
||
return best;
|
||
}
|
common/city.h | ||
---|---|---|
void city_size_set(struct city *pcity, citizens size);
|
||
citizens city_specialists(const struct city *pcity);
|
||
int city_superspecialists(const struct city *pcity);
|
||
citizens player_content_citizens(const struct player *pplayer);
|
||
citizens player_angry_citizens(const struct player *pplayer);
|
common/networking/packets.def | ||
---|---|---|
UINT16 num_city_styles;
|
||
UINT16 terrain_count;
|
||
UINT16 num_specialist_types;
|
||
UINT16 num_normal_specialists;
|
||
UINT16 num_nation_groups;
|
||
UINT16 num_nation_sets;
|
||
common/specialist.c | ||
---|---|---|
return game.control.num_specialist_types;
|
||
}
|
||
/**********************************************************************//**
|
||
Return the number of normal specialist_types.
|
||
**************************************************************************/
|
||
Specialist_type_id normal_specialist_count(void)
|
||
{
|
||
return game.control.num_normal_specialists;
|
||
}
|
||
/**********************************************************************//**
|
||
Return the specialist index.
|
||
... | ... | |
return name_translation_get(&sp->abbreviation);
|
||
}
|
||
/**********************************************************************//**
|
||
If this is a superspecialist: is not included into city population,
|
||
is not controlled by player.
|
||
**************************************************************************/
|
||
bool is_super_specialist_id(Specialist_type_id sp)
|
||
{
|
||
if (sp >= game.control.num_specialist_types) {
|
||
return FALSE;
|
||
}
|
||
return sp >= game.control.num_normal_specialists;
|
||
}
|
||
/**********************************************************************//**
|
||
If this is a normal specialist: included into city population,
|
||
can be reassigned by player.
|
||
**************************************************************************/
|
||
bool is_normal_specialist_id(Specialist_type_id sp)
|
||
{
|
||
if (sp < 0) {
|
||
return FALSE;
|
||
}
|
||
return sp < game.control.num_normal_specialists;
|
||
}
|
||
/**********************************************************************//**
|
||
If this is a superspecialist: is not included into city population,
|
||
is not controlled by player. Assumes a valid specialist pointer.
|
||
**************************************************************************/
|
||
bool is_super_specialist(const struct specialist *sp)
|
||
{
|
||
return is_super_specialist_id(specialist_index(sp));
|
||
}
|
||
/**********************************************************************//**
|
||
If this is a normal specialist: included into city population,
|
||
can be reassigned by player. Assumes a valid specialist pointer.
|
||
**************************************************************************/
|
||
bool is_normal_specialist(const struct specialist *sp){
|
||
return is_normal_specialist_id(specialist_index(sp));
|
||
}
|
||
/**********************************************************************//**
|
||
Return a string containing all the specialist abbreviations, for instance
|
||
"E/S/T".
|
common/specialist.h | ||
---|---|---|
/* General specialist accessor functions. */
|
||
Specialist_type_id specialist_count(void);
|
||
Specialist_type_id normal_specialist_count(void);
|
||
Specialist_type_id specialist_index(const struct specialist *sp);
|
||
Specialist_type_id specialist_number(const struct specialist *sp);
|
||
... | ... | |
const char *specialist_plural_translation(const struct specialist *sp);
|
||
const char *specialist_abbreviation_translation(const struct specialist *sp);
|
||
bool is_super_specialist_id(Specialist_type_id sp);
|
||
bool is_normal_specialist_id(Specialist_type_id sp);
|
||
bool is_super_specialist(const struct specialist *sp);
|
||
bool is_normal_specialist(const struct specialist *sp);
|
||
/* Ancillary routines */
|
||
const char *specialists_abbreviation_string(void);
|
||
const char *specialists_string(const citizens *specialist_list);
|
||
... | ... | |
} \
|
||
}
|
||
#define normal_specialist_type_iterate(sp) \
|
||
{ \
|
||
Specialist_type_id sp; \
|
||
\
|
||
for (sp = 0; sp < normal_specialist_count(); sp++) {
|
||
#define normal_specialist_type_iterate_end \
|
||
} \
|
||
}
|
||
#define super_specialist_type_iterate(sp) \
|
||
{ \
|
||
Specialist_type_id sp; \
|
||
\
|
||
for (sp = normal_specialist_count(); sp < specialist_count(); sp++) {
|
||
#define super_specialist_type_iterate_end \
|
||
} \
|
||
}
|
||
#define specialist_type_re_active_iterate(_p) \
|
||
specialist_type_iterate(_p##_) { \
|
||
struct specialist *_p = specialist_by_number(_p##_); \
|
server/cityhand.c | ||
---|---|---|
return;
|
||
}
|
||
if (to < 0 || to >= specialist_count()
|
||
|| from < 0 || from >= specialist_count()
|
||
if (!is_normal_specialist_id(to)
|
||
|| !is_normal_specialist_id(from)
|
||
|| !city_can_use_specialist(pcity, to)
|
||
|| pcity->specialists[from] == 0) {
|
||
/* This could easily just be due to clicking faster on the specialist
|
||
... | ... | |
city_map_update_worker(pcity, ptile);
|
||
specialist_type_iterate(i) {
|
||
normal_specialist_type_iterate(i) {
|
||
if (pcity->specialists[i] > 0) {
|
||
pcity->specialists[i]--;
|
||
break;
|
||
}
|
||
} specialist_type_iterate_end;
|
||
} normal_specialist_type_iterate_end;
|
||
city_refresh(pcity);
|
||
sanity_check_city(pcity);
|
server/citytools.c | ||
---|---|---|
bool dipl_invest)
|
||
{
|
||
int i;
|
||
int ppl = 0;
|
||
int ppl = 0; /* Counter of citizens for sanity check */
|
||
fc_assert(!pcity->server.needs_arrange);
|
||
... | ... | |
packet->specialists_size = specialist_count();
|
||
specialist_type_iterate(sp) {
|
||
packet->specialists[sp] = pcity->specialists[sp];
|
||
ppl += packet->specialists[sp];
|
||
if (is_normal_specialist_id(sp)) {
|
||
ppl += packet->specialists[sp];
|
||
}
|
||
} specialist_type_iterate_end;
|
||
/* The nationality of the citizens. */
|
server/cityturn.c | ||
---|---|---|
}
|
||
} city_tile_iterate_skip_free_worked_end;
|
||
specialist_type_iterate(sp) {
|
||
normal_specialist_type_iterate(sp) {
|
||
pcity->specialists[sp] = cmr->specialists[sp];
|
||
} specialist_type_iterate_end;
|
||
} normal_specialist_type_iterate_end;
|
||
}
|
||
/**********************************************************************//**
|
||
... | ... | |
fc_assert_ret_val(0 < change, 0);
|
||
specialist_type_iterate(sp) {
|
||
normal_specialist_type_iterate(sp) {
|
||
citizens fix = MIN(want, pcity->specialists[sp]);
|
||
pcity->specialists[sp] -= fix;
|
||
want -= fix;
|
||
} specialist_type_iterate_end;
|
||
} normal_specialist_type_iterate_end;
|
||
return change - want;
|
||
}
|
server/ruleset/ruleload.c | ||
---|---|---|
#define RESOURCE_SECTION_PREFIX "resource_"
|
||
#define GOODS_SECTION_PREFIX "goods_"
|
||
#define SPECIALIST_SECTION_PREFIX "specialist_"
|
||
#define SUPER_SPECIALIST_SECTION_PREFIX "super_specialist_"
|
||
#define TERRAIN_SECTION_PREFIX "terrain_"
|
||
#define UNIT_CLASS_SECTION_PREFIX "unitclass_"
|
||
#define UNIT_SECTION_PREFIX "unit_"
|
||
... | ... | |
const char *path,
|
||
struct veteran_system **vsystem, char *err,
|
||
size_t err_len);
|
||
static bool load_specialist(const struct section *psection,
|
||
struct specialist *s,
|
||
struct section_file *file);
|
||
char *script_buffer = NULL;
|
||
char *parser_buffer = NULL;
|
||
... | ... | |
filename));
|
||
}
|
||
/**********************************************************************//**
|
||
Load a single specialist or superspecialist section
|
||
**************************************************************************/
|
||
static bool load_specialist(const struct section *psection,
|
||
struct specialist *s,
|
||
struct section_file *file)
|
||
{
|
||
struct requirement_vector *reqs;
|
||
const char *sec_name = section_name(psection);
|
||
const char *item, *tag;
|
||
if (!ruleset_load_names(&s->name, NULL, file, sec_name)) {
|
||
return FALSE;
|
||
}
|
||
item = secfile_lookup_str_default(file, untranslated_name(&s->name),
|
||
"%s.short_name", sec_name);
|
||
name_set(&s->abbreviation, NULL, item);
|
||
tag = secfile_lookup_str(file, "%s.graphic", sec_name);
|
||
if (tag == NULL) {
|
||
ruleset_error(NULL, LOG_ERROR,
|
||
"\"%s\": No graphic tag for specialist at %s.",
|
||
secfile_name(file), sec_name);
|
||
return FALSE;
|
||
}
|
||
sz_strlcpy(s->graphic_str, tag);
|
||
sz_strlcpy(s->graphic_alt,
|
||
secfile_lookup_str_default(file, "-",
|
||
"%s.graphic_alt", sec_name));
|
||
reqs = lookup_req_list(file, sec_name, "reqs", specialist_rule_name(s));
|
||
if (reqs == NULL) {
|
||
return FALSE;
|
||
}
|
||
requirement_vector_copy(&s->reqs, reqs);
|
||
s->helptext = lookup_strvec(file, sec_name, "helptext");
|
||
return TRUE;
|
||
}
|
||
/**********************************************************************//**
|
||
Load cities.ruleset file
|
||
**************************************************************************/
|
||
... | ... | |
struct rscompat_info *compat)
|
||
{
|
||
const char *filename = secfile_name(file);
|
||
const char *item;
|
||
struct section_list *sec;
|
||
struct section_list *sec, *ssec;
|
||
int specs_count;
|
||
bool ok = TRUE;
|
||
int i = 0;
|
||
if (!rscompat_check_cap_and_version(file, filename, compat)) {
|
||
return FALSE;
|
||
... | ... | |
/* Specialist options */
|
||
sec = secfile_sections_by_name_prefix(file, SPECIALIST_SECTION_PREFIX);
|
||
if (section_list_size(sec) >= SP_MAX) {
|
||
ssec = secfile_sections_by_name_prefix(file, SUPER_SPECIALIST_SECTION_PREFIX);
|
||
specs_count = section_list_size(sec) + section_list_size(ssec);
|
||
if (specs_count >= SP_MAX) {
|
||
ruleset_error(NULL, LOG_ERROR,
|
||
"\"%s\": Too many specialists (%d, max %d).",
|
||
filename, section_list_size(sec), SP_MAX);
|
||
... | ... | |
}
|
||
if (ok) {
|
||
int i = 0;
|
||
const char *tag;
|
||
game.control.num_specialist_types = section_list_size(sec);
|
||
game.control.num_specialist_types = specs_count;
|
||
section_list_iterate(sec, psection) {
|
||
struct specialist *s = specialist_by_number(i);
|
||
struct requirement_vector *reqs;
|
||
const char *sec_name = section_name(psection);
|
||
if (!ruleset_load_names(&s->name, NULL, file, sec_name)) {
|
||
ok = FALSE;
|
||
break;
|
||
}
|
||
item = secfile_lookup_str_default(file, untranslated_name(&s->name),
|
||
"%s.short_name", sec_name);
|
||
name_set(&s->abbreviation, NULL, item);
|
||
tag = secfile_lookup_str(file, "%s.graphic", sec_name);
|
||
if (tag == NULL) {
|
||
ruleset_error(NULL, LOG_ERROR,
|
||
"\"%s\": No graphic tag for specialist at %s.",
|
||
filename, sec_name);
|
||
ok = FALSE;
|
||
break;
|
||
}
|
||
sz_strlcpy(s->graphic_str, tag);
|
||
sz_strlcpy(s->graphic_alt,
|
||
secfile_lookup_str_default(file, "-",
|
||
"%s.graphic_alt", sec_name));
|
||
ok = load_specialist(psection, s, file);
|
||
reqs = lookup_req_list(file, sec_name, "reqs", specialist_rule_name(s));
|
||
if (reqs == NULL) {
|
||
ok = FALSE;
|
||
if (!ok) {
|
||
break;
|
||
}
|
||
requirement_vector_copy(&s->reqs, reqs);
|
||
s->helptext = lookup_strvec(file, sec_name, "helptext");
|
||
if (requirement_vector_size(&s->reqs) == 0 && DEFAULT_SPECIALIST == -1) {
|
||
DEFAULT_SPECIALIST = i;
|
||
... | ... | |
} section_list_iterate_end;
|
||
}
|
||
if (ok && DEFAULT_SPECIALIST == -1) {
|
||
ruleset_error(NULL, LOG_ERROR,
|
||
"\"%s\": must give a min_size of 0 for at least one "
|
||
"specialist type.", filename);
|
||
ok = FALSE;
|
||
if (ok){
|
||
if (DEFAULT_SPECIALIST == -1) {
|
||
ruleset_error(NULL, LOG_ERROR,
|
||
"\"%s\": must have zero reqs for at least one "
|
||
"specialist type.", filename);
|
||
ok = FALSE;
|
||
} else {
|
||
game.control.num_normal_specialists = i;
|
||
}
|
||
}
|
||
section_list_destroy(sec);
|
||
sec = NULL;
|
||
if (ok) {
|
||
section_list_iterate(ssec, psection) {
|
||
struct specialist *s = specialist_by_number(i);
|
||
ok = load_specialist(psection, s, file);
|
||
if (!ok) {
|
||
break;
|
||
}
|
||
i++;
|
||
} section_list_iterate_end;
|
||
}
|
||
section_list_destroy(ssec);
|
||
ssec = NULL;
|
||
if (ok) {
|
||
/* City Parameters */
|
||
server/savegame/savegame3.c | ||
---|---|---|
city_size_set(pcity, size);
|
||
for (i = 0; i < loading->specialist.size; i++) {
|
||
Specialist_type_id si = specialist_index(loading->specialist.order[i]);
|
||
sg_warn_ret_val(secfile_lookup_int(loading->file, &value, "%s.nspe%d",
|
||
citystr, i),
|
||
FALSE, "%s", secfile_error());
|
||
pcity->specialists[specialist_index(loading->specialist.order[i])]
|
||
= (citizens)value;
|
||
sp_count += value;
|
||
pcity->specialists[si] = (citizens)value;
|
||
if (is_normal_specialist_id(si)) {
|
||
sp_count += value;
|
||
}
|
||
}
|
||
partner = secfile_lookup_int_default(loading->file, 0, "%s.traderoute0", citystr);
|
server/score.c | ||
---|---|---|
+ pplayer->score.unhappy
|
||
+ pplayer->score.angry);
|
||
specialist_type_iterate(sp) {
|
||
normal_specialist_type_iterate(sp) {
|
||
count += pplayer->score.specialists[sp];
|
||
} specialist_type_iterate_end;
|
||
} normal_specialist_type_iterate_end;
|
||
return count;
|
||
}
|
tools/ruleutil/rulesave.c | ||
---|---|---|
struct specialist *s = specialist_by_number(sp);
|
||
char path[512];
|
||
fc_snprintf(path, sizeof(path), "specialist_%d", sect_idx++);
|
||
fc_snprintf(path, sizeof(path),
|
||
is_super_specialist_id(sp)
|
||
? "super_specialist_%d" : "specialist_%d", sect_idx++);
|
||
save_name_translation(sfile, &(s->name), path);
|
||