Project

General

Profile

Feature #1375 » main-superspecialists-basic.patch

Alexandr Ignatiev, 05/08/2025 10:48 PM

View differences:

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);
(1-1/3)