[Freeciv-Dev] (PR#12615) requirements for city styles
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=12615 >
This patch changes city styles to use requirements (instead of a single
tech_req). This partially fulfills a request by the artists (CapTVK
wanted to be able to specialize city styles more). However since the
city style is done per-player only player and world-range requirements
may be checked.
-jason
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.480
diff -u -r1.480 packhand.c
--- client/packhand.c 24 Mar 2005 16:41:41 -0000 1.480
+++ client/packhand.c 24 Mar 2005 19:04:53 -0000
@@ -2502,7 +2502,7 @@
**************************************************************************/
void handle_ruleset_city(struct packet_ruleset_city *packet)
{
- int id;
+ int id, j;
struct citystyle *cs;
id = packet->style_id;
@@ -2513,7 +2513,12 @@
}
cs = &city_styles[id];
- cs->techreq = packet->techreq;
+ for (j = 0; j < MAX_NUM_REQS; j++) {
+ cs->req[j] = req_from_values(packet->req_type[j],
+ packet->req_range[j],
+ packet->req_survives[j],
+ packet->req_value[j]);
+ }
cs->replaced_by = packet->replaced_by;
sz_strlcpy(cs->name_orig, packet->name);
Index: client/gui-gtk-2.0/dialogs.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/dialogs.c,v
retrieving revision 1.93
diff -u -r1.93 dialogs.c
--- client/gui-gtk-2.0/dialogs.c 21 Mar 2005 16:37:52 -0000 1.93
+++ client/gui-gtk-2.0/dialogs.c 24 Mar 2005 19:04:53 -0000
@@ -1756,7 +1756,7 @@
SPRITE *s;
GtkTreeIter it;
- if (city_styles[i].techreq != A_NONE) {
+ if (city_style_has_requirements(&city_styles[i])) {
continue;
}
@@ -2010,7 +2010,7 @@
/* Select city style for chosen nation. */
cs = get_nation_city_style(selected_nation);
for (i = 0, j = 0; i < game.styles_count; i++) {
- if (city_styles[i].techreq != A_NONE) {
+ if (city_style_has_requirements(&city_styles[i])) {
continue;
}
Index: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.320
diff -u -r1.320 city.c
--- common/city.c 24 Mar 2005 16:41:41 -0000 1.320
+++ common/city.c 24 Mar 2005 19:04:53 -0000
@@ -663,24 +663,12 @@
bool city_can_use_specialist(const struct city *pcity,
Specialist_type_id type)
{
- int i;
-
if (pcity->size < game.rgame.specialists[type].min_size) {
return FALSE;
}
- for (i = 0; i < MAX_NUM_REQS; i++) {
- struct requirement *req = &game.rgame.specialists[type].req[i];
-
- if (req->source.type == REQ_NONE) {
- break; /* Short-circuit any more checks. */
- } else if (!is_req_active(TARGET_CITY, city_owner(pcity), pcity,
- B_LAST, NULL, req)) {
- return FALSE;
- }
- }
-
- return TRUE;
+ return are_reqs_active(TARGET_CITY, city_owner(pcity), pcity, B_LAST, NULL,
+ game.rgame.specialists[type].req, MAX_NUM_REQS);
}
/**************************************************************************
@@ -1257,7 +1245,8 @@
while ((replace = city_styles[prev].replaced_by) != -1) {
prev = replace;
- if (get_invention(plr, city_styles[replace].techreq) == TECH_KNOWN) {
+ if (are_reqs_active(TARGET_PLAYER, plr, NULL, B_LAST, NULL,
+ city_styles[replace].req, MAX_NUM_REQS)) {
style = replace;
}
}
@@ -1319,6 +1308,15 @@
return city_styles[style].name_orig;
}
+/****************************************************************************
+ Return whether the style has any requirements. Styles without requirements
+ are special cases since only these may be used as starting city styles.
+****************************************************************************/
+bool city_style_has_requirements(const struct citystyle *style)
+{
+ return style->req[0].source.type != REQ_NONE;
+}
+
/**************************************************************************
Compute and optionally apply the change-production penalty for the given
production change (to target,is_unit) in the given city (pcity).
Index: common/city.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.h,v
retrieving revision 1.202
diff -u -r1.202 city.h
--- common/city.h 8 Mar 2005 00:43:26 -0000 1.202
+++ common/city.h 24 Mar 2005 19:04:53 -0000
@@ -321,7 +321,7 @@
char graphic_alt[MAX_LEN_NAME];
char citizens_graphic[MAX_LEN_NAME];
char citizens_graphic_alt[MAX_LEN_NAME];
- int techreq; /* tech required to use a style */
+ struct requirement req[MAX_NUM_REQS];
int replaced_by; /* index to replacing style */
/* client side-only: */
int tresh[MAX_CITY_TILES]; /* treshholds - what city size to use a tile */
@@ -469,6 +469,7 @@
int get_style_by_name_orig(const char *);
const char *get_city_style_name(int style);
char* get_city_style_name_orig(int style);
+bool city_style_has_requirements(const struct citystyle *style);
struct city *is_enemy_city_tile(const struct tile *ptile,
const struct player *pplayer);
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.98
diff -u -r1.98 packets.def
--- common/packets.def 24 Mar 2005 16:41:41 -0000 1.98
+++ common/packets.def 24 Mar 2005 19:04:54 -0000
@@ -1123,10 +1123,13 @@
PACKET_RULESET_CITY=103;sc,lsend
UINT8 style_id;
- UINT8 techreq;
STRING name[MAX_LEN_NAME];
STRING citizens_graphic[MAX_LEN_NAME];
STRING citizens_graphic_alt[MAX_LEN_NAME];
+ UINT8 req_type[MAX_NUM_REQS];
+ UINT8 req_range[MAX_NUM_REQS];
+ UINT8 req_value[MAX_NUM_REQS];
+ BOOL req_survives[MAX_NUM_REQS];
STRING graphic[MAX_LEN_NAME];
STRING graphic_alt[MAX_LEN_NAME];
SINT8 replaced_by;
Index: common/requirements.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/requirements.c,v
retrieving revision 1.6
diff -u -r1.6 requirements.c
--- common/requirements.c 23 Mar 2005 02:07:44 -0000 1.6
+++ common/requirements.c 24 Mar 2005 19:04:54 -0000
@@ -614,3 +614,39 @@
assert(0);
return FALSE;
}
+
+/****************************************************************************
+ Checks the requirement(s) to see if they are active on the given target.
+
+ target gives the type of the target
+ (player,city,building,tile) give the exact target
+
+ reqs gives the requirement array; num_reqs is the size of the array. This
+ array may be REQ_NONE-terminated, otherwise all requirements in it will
+ be checked. The function returns TRUE only if all requirements are active.
+
+ Make sure you give all aspects of the target when calling this function:
+ for instance if you have TARGET_CITY pass the city's owner as the target
+ player as well as the city itself as the target city.
+****************************************************************************/
+bool are_reqs_active(enum target_type target,
+ const struct player *target_player,
+ const struct city *target_city,
+ Impr_Type_id target_building,
+ const struct tile *target_tile,
+ const struct requirement *reqs, int num_reqs)
+{
+ int i;
+
+ for (i = 0; i < num_reqs; i++) {
+ if (reqs[i].source.type == REQ_NONE) {
+ break; /* Short-circuit any more checks. */
+ } else if (!is_req_active(target, target_player, target_city,
+ target_building, target_tile,
+ &reqs[i])) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
Index: common/requirements.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/requirements.h,v
retrieving revision 1.4
diff -u -r1.4 requirements.h
--- common/requirements.h 23 Mar 2005 02:07:44 -0000 1.4
+++ common/requirements.h 24 Mar 2005 19:04:54 -0000
@@ -81,6 +81,13 @@
TYPED_LIST_ITERATE(struct requirement, req_list, preq)
#define requirement_list_iterate_end LIST_ITERATE_END
+#define SPECVEC_TAG requirement
+#define SPECVEC_TYPE struct requirement
+#include "specvec.h"
+#define requirement_vector_iterate(req_vec, preq) \
+ TYPED_VECTOR_ITERATE(struct requirement, req_vec, preq)
+#define requirement_vector_iterate_end VECTOR_ITERATE_END
+
struct req_source req_source_from_str(const char *type, const char *value);
struct req_source req_source_from_values(int type, int value);
void req_source_get_values(struct req_source *source, int *type, int *value);
@@ -100,6 +107,12 @@
Impr_Type_id target_building,
const struct tile *target_tile,
const struct requirement *req);
+bool are_reqs_active(enum target_type target,
+ const struct player *target_player,
+ const struct city *target_city,
+ Impr_Type_id target_building,
+ const struct tile *target_tile,
+ const struct requirement *reqs, int num_reqs);
int count_buildings_in_range(enum target_type target,
const struct player *target_player,
Index: data/default/cities.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/default/cities.ruleset,v
retrieving revision 1.14
diff -u -r1.14 cities.ruleset
--- data/default/cities.ruleset 8 Dec 2004 16:53:53 -0000 1.14
+++ data/default/cities.ruleset 24 Mar 2005 19:04:54 -0000
@@ -48,7 +48,7 @@
; more info on city tiles
; citizens_graphic = group of citizens tiles to use, see citizens/small
; spec for more info on citizens tiles
-; tech = technology required for style to be used
+; reqs = requirements for this city style (see README.effects)
; replaced_by = which style replaced this one
[citystyle_european]
@@ -57,7 +57,7 @@
graphic_alt = "-"
citizens_graphic = "ancient"
citizens_graphic_alt = "generic"
-tech = "None"
+; No reqs
replaced_by = "Renaissance"
[citystyle_classical]
@@ -66,7 +66,7 @@
graphic_alt = "-"
citizens_graphic = "ancient"
citizens_graphic_alt = "generic"
-tech = "None"
+; No reqs
replaced_by = "Renaissance"
[citystyle_tropical]
@@ -75,7 +75,7 @@
graphic_alt = "city.european"
citizens_graphic = "ancient"
citizens_graphic_alt = "generic"
-tech = "None"
+; No reqs
replaced_by = "Renaissance"
[citystyle_asian]
@@ -84,7 +84,7 @@
graphic_alt = "city.classical"
citizens_graphic = "ancient"
citizens_graphic_alt = "generic"
-tech = "None"
+; No reqs
replaced_by = "Renaissance"
[citystyle_renaissance]
@@ -93,7 +93,9 @@
graphic_alt = "-"
citizens_graphic = "renaissance"
citizens_graphic_alt = "generic"
-tech = "University"
+reqs = { "type", "name", "range"
+ "tech", "University", "Player"
+ }
replaced_by = "Industrial"
[citystyle_industrial]
@@ -102,7 +104,9 @@
graphic_alt = "-"
citizens_graphic = "industrial"
citizens_graphic_alt = "generic"
-tech = "Railroad"
+reqs = { "type", "name", "range"
+ "tech", "Railroad", "Player"
+ }
replaced_by = "Modern"
[citystyle_modern]
@@ -111,7 +115,9 @@
graphic_alt = "-"
citizens_graphic = "modern"
citizens_graphic_alt = "generic"
-tech = "Automobile"
+reqs = { "type", "name", "range"
+ "tech", "Automobile", "Player"
+ }
replaced_by = "PostModern"
[citystyle_postmodern]
@@ -120,5 +126,7 @@
graphic_alt = "-"
citizens_graphic = "postmodern"
citizens_graphic_alt = "generic"
-tech = "Superconductors"
+reqs = { "type", "name", "range"
+ "tech", "Superconductors", "Player"
+ }
replaced_by = "-"
Index: server/ruleset.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/ruleset.c,v
retrieving revision 1.235
diff -u -r1.235 ruleset.c
--- server/ruleset.c 24 Mar 2005 16:41:42 -0000 1.235
+++ server/ruleset.c 24 Mar 2005 19:04:55 -0000
@@ -195,6 +195,52 @@
return datafile_options;
}
+/**************************************************************************
+ Load a requirement list. The list is returned as a static vector
+ (callers need not worry about freeing anything).
+**************************************************************************/
+static struct requirement_vector *lookup_req_list(struct section_file *file,
+ const char *sec,
+ const char *sub)
+{
+ char *type, *name;
+ int j;
+ const char *filename;
+ static struct requirement_vector list;
+
+ filename = secfile_filename(file);
+
+ requirement_vector_reserve(&list, 0);
+
+ for (j = 0;
+ (type = secfile_lookup_str_default(file, NULL, "%s.%s%d.type",
+ sec, sub, j));
+ j++) {
+ char *range;
+ bool survives;
+ struct requirement req;
+
+ name = secfile_lookup_str(file, "%s.%s%d.name", sec, sub, j);
+ range = secfile_lookup_str(file, "%s.%s%d.range", sec, sub, j);
+
+ survives = secfile_lookup_bool_default(file, FALSE,
+ "%s.%s%d.survives", sec, sub, j);
+
+ req = req_from_str(type, range, survives, name);
+ if (req.source.type == REQ_LAST) {
+ /* Error. Log it, clear the req and continue. */
+ freelog(LOG_ERROR,
+ /* TRANS: Obscure ruleset error */
+ _("Section %s has unknown req: \"%s\" \"%s\" (%s)"),
+ sec, type, name, filename);
+ req.source.type = REQ_NONE;
+ }
+
+ requirement_vector_append(&list, &req);
+ }
+
+ return &list;
+}
/**************************************************************************
Lookup a string prefix.entry in the file and return the corresponding
@@ -2097,7 +2143,7 @@
pl->city_style = 0;
}
- while (city_styles[pl->city_style].techreq != A_NONE) {
+ while (city_styles[pl->city_style].req[0].source.type != REQ_NONE) {
if (pl->city_style == 0) {
freelog(LOG_FATAL,
"Nation %s: the default city style is not available "
@@ -2223,7 +2269,7 @@
static void load_ruleset_cities(struct section_file *file)
{
char **styles, *replacement;
- int i, nval;
+ int i, nval, j;
const char *filename = secfile_filename(file);
char **specialist_names;
@@ -2320,6 +2366,8 @@
/* Get rest: */
for( i=0; i<game.styles_count; i++) {
+ struct requirement_vector *reqs;
+
sz_strlcpy(city_styles[i].graphic,
secfile_lookup_str(file, "%s.graphic", styles[i]));
sz_strlcpy(city_styles[i].graphic_alt,
@@ -2330,9 +2378,17 @@
sz_strlcpy(city_styles[i].citizens_graphic_alt,
secfile_lookup_str_default(file, "generic",
"%s.citizens_graphic_alt", styles[i]));
- city_styles[i].techreq = lookup_tech(file, styles[i], "tech", TRUE,
- filename, city_styles[i].name);
-
+
+ reqs = lookup_req_list(file, styles[i], "reqs");
+ for (j = 0; j < MAX_NUM_REQS; j++) {
+ if (reqs->size > j) {
+ city_styles[i].req[j] = reqs->p[j];
+ } else {
+ city_styles[i].req[j].source.type = REQ_NONE;
+ memset(&city_styles[i].req[j], 0, sizeof(city_styles[i].req[j]));
+ }
+ }
+
replacement = secfile_lookup_str(file, "%s.replaced_by", styles[i]);
if( strcmp(replacement, "-") == 0) {
city_styles[i].replaced_by = -1;
@@ -2352,52 +2408,6 @@
}
/**************************************************************************
-Load effects requirement list.
-**************************************************************************/
-static void load_req_list(struct section_file *file,
- const char *sec, const char *sub,
- bool neg, struct effect *peffect)
-{
- char *type, *name;
- int j;
- const char *filename;
-
- filename = secfile_filename(file);
-
- for (j = 0;
- (type = secfile_lookup_str_default(file, NULL, "%s.%s%d.type",
- sec, sub, j));
- j++) {
- char *range;
- bool survives;
- struct requirement req;
-
- name = secfile_lookup_str(file, "%s.%s%d.name", sec, sub, j);
- range = secfile_lookup_str(file, "%s.%s%d.range", sec, sub, j);
-
- survives = secfile_lookup_bool_default(file, FALSE,
- "%s.%s%d.survives", sec, sub, j);
-
- req = req_from_str(type, range, survives, name);
- if (req.source.type == REQ_LAST) {
- /* Error. Log it, clear the req and continue. */
- freelog(LOG_ERROR,
- /* TRANS: Obscure ruleset error */
- _("Section %s has unknown req: \"%s\" \"%s\" (%s)"),
- sec, type, name, filename);
- req.source.type = REQ_NONE;
- } else {
- struct requirement *preq;
-
- preq = fc_malloc(sizeof(*preq));
- *preq = req;
-
- effect_req_append(peffect, neg, preq);
- }
- }
-}
-
-/**************************************************************************
Load effects.ruleset file
**************************************************************************/
static void load_ruleset_effects(struct section_file *file)
@@ -2431,8 +2441,18 @@
peffect = effect_new(eff, value);
- load_req_list(file, sec[i], "reqs", FALSE, peffect);
- load_req_list(file, sec[i], "nreqs", TRUE, peffect);
+ requirement_vector_iterate(lookup_req_list(file, sec[i], "reqs"), req) {
+ struct requirement *preq = fc_malloc(sizeof(*preq));
+
+ *preq = *req;
+ effect_req_append(peffect, FALSE, preq);
+ } requirement_vector_iterate_end;
+ requirement_vector_iterate(lookup_req_list(file, sec[i], "nreqs"), req) {
+ struct requirement *preq = fc_malloc(sizeof(*preq));
+
+ *preq = *req;
+ effect_req_append(peffect, TRUE, preq);
+ } requirement_vector_iterate_end;
}
free(sec);
@@ -2933,13 +2953,20 @@
static void send_ruleset_cities(struct conn_list *dest)
{
struct packet_ruleset_city city_p;
- int k;
+ int k, j;
for( k=0; k<game.styles_count; k++) {
city_p.style_id = k;
- city_p.techreq = city_styles[k].techreq;
city_p.replaced_by = city_styles[k].replaced_by;
+ for (j = 0; j < MAX_NUM_REQS; j++) {
+ req_get_values(&city_styles[k].req[j],
+ &city_p.req_type[j],
+ &city_p.req_range[j],
+ &city_p.req_survives[j],
+ &city_p.req_value[j]);
+ }
+
sz_strlcpy(city_p.name, city_styles[k].name_orig);
sz_strlcpy(city_p.graphic, city_styles[k].graphic);
sz_strlcpy(city_p.graphic_alt, city_styles[k].graphic_alt);
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.236
diff -u -r1.236 srv_main.c
--- server/srv_main.c 22 Mar 2005 04:03:35 -0000 1.236
+++ server/srv_main.c 24 Mar 2005 19:04:55 -0000
@@ -1166,8 +1166,8 @@
/* check sanity of the packet sent by client */
if (nation_no < 0 || nation_no >= game.nation_count ||
- city_style < 0 || city_style >= game.styles_count ||
- city_styles[city_style].techreq != A_NONE
+ city_style < 0 || city_style >= game.styles_count
+ || city_style_has_requirement(&city_styles[city_style])
|| !nations_available[nation_no]) {
return;
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Freeciv-Dev] (PR#12615) requirements for city styles,
Jason Short <=
|
|