[Freeciv-Dev] (PR#13040) Meta-Ticket: Requirements unification
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: |
[Freeciv-Dev] (PR#13040) Meta-Ticket: Requirements unification |
From: |
"Vasco Alexandre da Silva Costa" <vasc@xxxxxxxxxxxxxx> |
Date: |
Wed, 11 May 2005 07:08:36 -0700 |
Reply-to: |
bugs@xxxxxxxxxxx |
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=13040 >
What this patch does:
* Replace the use of static requirement arrays with dynamic requirement
vectors.
* Parse 'negated' requirement attribute to enable more complex
requirements. Make is_req_active take 'negated' attribute into
consideration.
A later patch will make effects also use the new complex requirement
vectors instead of using custom reqs/nreqs requirement lists.
Index: ai/aihand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aihand.c,v
retrieving revision 1.115
diff -u -u -r1.115 aihand.c
--- ai/aihand.c 7 May 2005 14:03:51 -0000 1.115
+++ ai/aihand.c 11 May 2005 13:59:22 -0000
@@ -290,7 +290,7 @@
if (ai->govt_reeval == 0) {
government_iterate(gov) {
int val = 0;
- int dist, i;
+ int dist;
if (gov->index == game.info.government_when_anarchy) {
continue; /* pointless */
@@ -328,14 +328,12 @@
/* FIXME: handle reqs other than technologies. */
dist = 0;
- for (i = 0; i < MAX_NUM_REQS; i++) {
- struct requirement *req = gov->req + i;
-
- if (req->source.type == REQ_TECH) {
+ requirement_vector_iterate(&gov->reqs, preq) {
+ if (preq->source.type == REQ_TECH) {
dist += MAX(1, num_unknown_techs_for_goal(pplayer,
- req->source.value.tech));
+ preq->source.value.tech));
}
- }
+ } requirement_list_iterate_end;
val = amortize(val, dist);
ai->government_want[gov->index] = val; /* Save want */
} government_iterate_end;
@@ -358,21 +356,17 @@
ai->goal.revolution = gov->index;
}
if (ai->government_want[gov->index] > ai->goal.govt.val) {
- int i;
-
ai->goal.govt.idx = gov->index;
ai->goal.govt.val = ai->government_want[gov->index];
/* FIXME: handle reqs other than technologies. */
ai->goal.govt.req = A_NONE;
- for (i = 0; i < MAX_NUM_REQS; i++) {
- struct requirement *req = gov->req + i;
-
- if (req->source.type == REQ_TECH) {
- ai->goal.govt.req = req->source.value.tech;
+ requirement_vector_iterate(&gov->reqs, preq) {
+ if (preq->source.type == REQ_TECH) {
+ ai->goal.govt.req = preq->source.value.tech;
break;
}
- }
+ } requirement_list_iterate_end;
}
} government_iterate_end;
/* Goodness of the ideal gov is calculated relative to the goodness of the
Index: ai/aitech.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aitech.c,v
retrieving revision 1.56
diff -u -u -r1.56 aitech.c
--- ai/aitech.c 30 Apr 2005 17:09:25 -0000 1.56
+++ ai/aitech.c 11 May 2005 13:59:22 -0000
@@ -231,18 +231,13 @@
}
if (iimpr != B_LAST
&& !can_player_build_improvement_direct(pplayer, iimpr)) {
- int j;
struct impr_type *building = get_improvement_type(iimpr);
- for (j = 0; j < MAX_NUM_REQS; j++) {
- struct requirement *req = &building->req[j];
-
- if (req->source.type == REQ_NONE) {
- break;
- } else if (req->source.type == REQ_TECH
- && (get_invention(pplayer, req->source.value.tech)
- != TECH_KNOWN)) {
- int iimprtech = req->source.value.tech;
+ requirement_vector_iterate(&building->reqs, preq) {
+ if (preq->source.type == REQ_TECH
+ && (get_invention(pplayer, preq->source.value.tech)
+ != TECH_KNOWN)) {
+ int iimprtech = preq->source.value.tech;
int imprcost = total_bulbs_required_for_goal(pplayer, iimprtech);
if (imprcost < cost || cost == 0) {
@@ -254,7 +249,7 @@
}
cost += imprcost;
}
- }
+ } requirement_list_iterate_end;
}
if (cost < best_cost) {
Index: client/helpdata.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/helpdata.c,v
retrieving revision 1.115
diff -u -u -r1.115 helpdata.c
--- client/helpdata.c 10 May 2005 19:08:54 -0000 1.115
+++ client/helpdata.c 11 May 2005 13:59:22 -0000
@@ -223,8 +223,6 @@
static void insert_allows(struct req_source *psource,
char *buf, size_t bufsz)
{
- int r1, r2;
-
buf[0] = '\0';
/* FIXME: show other data like range and survives. */
@@ -237,23 +235,18 @@
impr_type_iterate(impr_id) {
struct impr_type *building = get_improvement_type(impr_id);
- for (r1 = 0; r1 < MAX_NUM_REQS; r1++) {
- struct requirement *req = building->req + r1;
-
+ requirement_vector_iterate(&building->reqs, req) {
if (are_req_sources_equal(psource, &req->source)) {
char coreq_buf[512] = "";
- for (r2 = 0; r2 < MAX_NUM_REQS; r2++) {
- struct requirement *coreq = building->req + r2;
-
- if (coreq->source.type != REQ_NONE
- && !are_req_sources_equal(psource, &coreq->source)) {
+ requirement_vector_iterate(&building->reqs, coreq) {
+ if (!are_req_sources_equal(psource, &coreq->source)) {
char buf2[512];
COREQ_APPEND(get_req_source_text(&coreq->source,
buf2, sizeof(buf2)));
}
- }
+ } requirement_vector_iterate_end;
if (coreq_buf[0] == '\0') {
cat_snprintf(buf, bufsz, _("Allows %s."), building->name);
@@ -263,7 +256,7 @@
}
cat_snprintf(buf, bufsz, "\n");
}
- }
+ } requirement_vector_iterate_end;
} impr_type_iterate_end;
#undef COREQ_APPEND
@@ -1120,16 +1113,13 @@
}
government_iterate(g) {
- int j;
-
/* FIXME: this should tell the other requirements. */
- for (j = 0; j < MAX_NUM_REQS; j++) {
- if (g->req[j].source.type == REQ_TECH
- && g->req[j].source.value.tech == i) {
+ requirement_vector_iterate(&g->reqs, preq) {
+ if (preq->source.type == REQ_TECH && preq->source.value.tech == i) {
sprintf(buf + strlen(buf), _("* Allows changing government to %s.\n"),
g->name);
}
- }
+ } requirement_vector_iterate_end;
} government_iterate_end;
if (tech_flag(i, TF_BONUS_TECH)) {
sprintf(buf + strlen(buf), _("* The first player to research %s gets "
@@ -1253,7 +1243,6 @@
{
struct government *gov;
bool active_types[O_MAX];
- int j;
const size_t bufsz = 64000; /* FIXME: should be passed in */
/* Try to guess which output types that are active in this
@@ -1278,9 +1267,9 @@
if (gov->helptext[0] != '\0') {
sprintf(buf, "%s\n\n", _(gov->helptext));
}
- for (j = 0; j < MAX_NUM_REQS; j++) {
- insert_requirement(gov->req + j, buf, bufsz);
- }
+ requirement_vector_iterate(&gov->reqs, preq) {
+ insert_requirement(preq, buf, bufsz);
+ } requirement_vector_iterate_end;
#if 0
if (gov->max_rate < 100 && game.info.changable_tax) {
sprintf(buf + strlen(buf),
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.512
diff -u -u -r1.512 packhand.c
--- client/packhand.c 11 May 2005 00:13:21 -0000 1.512
+++ client/packhand.c 11 May 2005 13:59:24 -0000
@@ -2143,8 +2143,8 @@
b->name = b->name_orig;
sz_strlcpy(b->graphic_str, p->graphic_str);
sz_strlcpy(b->graphic_alt, p->graphic_alt);
- for (i = 0; i < MAX_NUM_REQS; i++) {
- b->req[i] = p->reqs[i];
+ for (i = 0; i < p->reqs_count; i++) {
+ requirement_vector_append(&b->reqs, &p->reqs[i]);
}
b->obsolete_by = p->obsolete_by;
b->build_cost = p->build_cost;
@@ -2197,8 +2197,8 @@
gov->index = p->id;
- for (j = 0; j < MAX_NUM_REQS; j++) {
- gov->req[j] = p->reqs[j];
+ for (j = 0; j < p->reqs_count; j++) {
+ requirement_vector_append(&gov->reqs, &p->reqs[j]);
}
gov->unit_happy_cost_factor = p->unit_happy_cost_factor;
@@ -2399,8 +2399,8 @@
}
cs = &city_styles[id];
- for (j = 0; j < MAX_NUM_REQS; j++) {
- cs->req[j] = packet->reqs[j];
+ for (j = 0; j < packet->reqs_count; j++) {
+ requirement_vector_append(&cs->reqs, &packet->reqs[j]);
}
cs->replaced_by = packet->replaced_by;
@@ -2424,6 +2424,7 @@
/* Must set num_specialist_types before iterating over them. */
SP_COUNT = packet->num_specialist_types;
DEFAULT_SPECIALIST = packet->default_specialist;
+ i = 0;
specialist_type_iterate(sp) {
struct specialist *s = get_specialist(sp);
int j;
@@ -2431,14 +2432,15 @@
sz_strlcpy(s->name, packet->specialist_name[sp]);
sz_strlcpy(s->short_name, packet->specialist_short_name[sp]);
- for (j = 0; j < MAX_NUM_REQS; j++) {
- int index = sp * MAX_NUM_REQS + j;
-
- s->req[j] = packet->specialist_reqs[index];
+ for (j = 0; j < packet->specialist_reqs_count[sp]; j++) {
+ requirement_vector_append(&s->reqs, &packet->specialist_reqs[i + j]);
}
+ i += j;
} specialist_type_iterate_end;
tileset_setup_specialist_types(tileset);
+ assert(packet->specialist_reqs_size == i);
+
for (i = 0; i < MAX_VET_LEVELS; i++) {
game.trireme_loss_chance[i] = packet->trireme_loss_chance[i];
game.work_veteran_chance[i] = packet->work_veteran_chance[i];
Index: client/gui-gtk-2.0/helpdlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/helpdlg.c,v
retrieving revision 1.48
diff -u -u -r1.48 helpdlg.c
--- client/gui-gtk-2.0/helpdlg.c 9 May 2005 18:42:19 -0000 1.48
+++ client/gui-gtk-2.0/helpdlg.c 11 May 2005 13:59:24 -0000
@@ -697,11 +697,14 @@
* Currently it's limited to 1 req but this code is partially prepared
* to be extended. Remember MAX_NUM_REQS is a compile-time
* definition. */
- for (i = 0; i < MIN(MAX_NUM_REQS, 1); i++) {
+ i = 0;
+ requirement_vector_iterate(&imp->reqs, preq) {
gtk_label_set_text(GTK_LABEL(help_ilabel[5 + i]),
- get_req_source_text(&imp->req[i].source,
+ get_req_source_text(&preq->source,
req_buf, sizeof(req_buf)));
- }
+ i++;
+ break;
+ } requirement_vector_iterate_end;
/* create_tech_tree(help_improvement_tree, 0, imp->tech_req, 3);*/
}
else {
@@ -739,11 +742,14 @@
* Currently it's limited to 1 req but this code is partially prepared
* to be extended. Remember MAX_NUM_REQS is a compile-time
* definition. */
- for (i = 0; i < MIN(MAX_NUM_REQS, 1); i++) {
+ i = 0;
+ requirement_vector_iterate(&imp->reqs, preq) {
gtk_label_set_text(GTK_LABEL(help_ilabel[3 + i]),
- get_req_source_text(&imp->req[i].source,
+ get_req_source_text(&preq->source,
req_buf, sizeof(req_buf)));
- }
+ i++;
+ break;
+ } requirement_vector_iterate_end;
if (tech_exists(imp->obsolete_by)) {
gtk_label_set_text(GTK_LABEL(help_wlabel[5]),
get_tech_name(game.player_ptr, imp->obsolete_by));
@@ -910,28 +916,22 @@
gtk_widget_show(w);
impr_type_iterate(j) {
- int k;
-
/* FIXME: need a more general mechanism for this, since this
* helptext needs to be shown in all possible req source types. */
- for (k = 0; k < MAX_NUM_REQS; k++) {
- struct requirement *req = &improvement_types[j].req[k];
-
- if (req->source.type == REQ_NONE) {
- break;
- } else if (req->source.type == REQ_BUILDING
- && req->source.value.building == i) {
+ requirement_vector_iterate(&improvement_types[j].reqs, preq) {
+ if (preq->source.type == REQ_BUILDING
+ && preq->source.value.building == i) {
hbox = gtk_hbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(help_vbox), hbox);
w = gtk_label_new(_("Allows"));
gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 0);
w = help_slink_new(improvement_types[j].name,
- is_great_wonder(j) ? HELP_WONDER
- : HELP_IMPROVEMENT);
+ is_great_wonder(j) ? HELP_WONDER
+ : HELP_IMPROVEMENT);
gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 0);
gtk_widget_show_all(hbox);
}
- }
+ } requirement_vector_iterate_end;
if(i==improvement_types[j].obsolete_by) {
hbox = gtk_hbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(help_vbox), hbox);
Index: common/capstr.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/capstr.c,v
retrieving revision 1.245
diff -u -u -r1.245 capstr.c
--- common/capstr.c 11 May 2005 00:13:21 -0000 1.245
+++ common/capstr.c 11 May 2005 13:59:24 -0000
@@ -82,7 +82,7 @@
* as long as possible. We want to maintain network compatibility with
* the stable branch for as long as possible.
*/
-#define CAPABILITY "+Freeciv.Devel.2005.May.11"
+#define CAPABILITY "+Freeciv.Devel.2005.May.11-1"
void init_our_capability(void)
{
Index: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.345
diff -u -u -r1.345 city.c
--- common/city.c 10 May 2005 19:08:54 -0000 1.345
+++ common/city.c 11 May 2005 13:59:24 -0000
@@ -394,7 +394,6 @@
bool can_build_improvement_direct(const struct city *pcity, Impr_type_id id)
{
const struct impr_type *building = get_improvement_type(id);
- int i;
if (!can_player_build_improvement_direct(city_owner(pcity), id)) {
return FALSE;
@@ -404,18 +403,9 @@
return FALSE;
}
- for (i = 0; i < MAX_NUM_REQS; i++) {
- if (building->req[i].source.type == REQ_NONE) {
- break;
- }
- if (!is_req_active(city_owner(pcity), pcity, NULL,
- pcity->tile, NULL, NULL, NULL,
- &building->req[i])) {
- return FALSE;
- }
- }
-
- return TRUE;
+ return are_reqs_active(city_owner(pcity), pcity, NULL,
+ pcity->tile, NULL, NULL, NULL,
+ &building->reqs);
}
/**************************************************************************
@@ -440,8 +430,7 @@
bool can_eventually_build_improvement(const struct city *pcity,
Impr_type_id id)
{
- int r;
- struct impr_type *building;
+ const struct impr_type *building = get_improvement_type(id);
/* Can the _player_ ever build this improvement? */
if (!can_player_eventually_build_improvement(city_owner(pcity), id)) {
@@ -450,19 +439,13 @@
/* Check for requirements that aren't met and that are unchanging (so
* they can never be met). */
- building = get_improvement_type(id);
- for (r = 0; r < MAX_NUM_REQS; r++) {
- if (building->req[r].source.type == REQ_NONE) {
- break;
- }
- if (is_req_unchanging(&building->req[r])
+ requirement_vector_iterate(&building->reqs, preq) {
+ if (is_req_unchanging(preq)
&& !is_req_active(city_owner(pcity), pcity, NULL,
- pcity->tile, NULL, NULL, NULL,
- &building->req[r])) {
+ pcity->tile, NULL, NULL, NULL, preq)) {
return FALSE;
}
- }
-
+ } requirement_list_iterate_end;
return TRUE;
}
@@ -537,7 +520,7 @@
{
return are_reqs_active(city_owner(pcity), pcity, NULL,
NULL, NULL, NULL, NULL,
- get_specialist(type)->req, MAX_NUM_REQS);
+ &get_specialist(type)->reqs);
}
/**************************************************************************
@@ -1126,7 +1109,7 @@
while ((replace = city_styles[prev].replaced_by) != -1) {
prev = replace;
if (are_reqs_active(plr, NULL, NULL, NULL, NULL, NULL, NULL,
- city_styles[replace].req, MAX_NUM_REQS)) {
+ &city_styles[replace].reqs)) {
style = replace;
}
}
@@ -1194,7 +1177,7 @@
****************************************************************************/
bool city_style_has_requirements(const struct citystyle *style)
{
- return style->req[0].source.type != REQ_NONE;
+ return (requirement_vector_size(&style->reqs) > 0);
}
/**************************************************************************
@@ -2346,8 +2329,14 @@
**************************************************************************/
void city_styles_alloc(int num)
{
+ int i;
+
city_styles = fc_calloc(num, sizeof(struct citystyle));
game.control.styles_count = num;
+
+ for (i = 0; i < game.control.styles_count; i++) {
+ requirement_vector_init(&city_styles[i].reqs);
+ }
}
/**************************************************************************
@@ -2355,6 +2344,12 @@
**************************************************************************/
void city_styles_free(void)
{
+ int i;
+
+ for (i = 0; i < game.control.styles_count; i++) {
+ requirement_vector_free(&city_styles[i].reqs);
+ }
+
free(city_styles);
city_styles = NULL;
game.control.styles_count = 0;
Index: common/city.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.h,v
retrieving revision 1.213
diff -u -u -r1.213 city.h
--- common/city.h 10 May 2005 19:08:54 -0000 1.213
+++ common/city.h 11 May 2005 13:59:24 -0000
@@ -331,7 +331,7 @@
char graphic_alt[MAX_LEN_NAME];
char citizens_graphic[MAX_LEN_NAME];
char citizens_graphic_alt[MAX_LEN_NAME];
- struct requirement req[MAX_NUM_REQS];
+ struct requirement_vector reqs;
int replaced_by; /* index to replacing style */
/* client side-only: */
int tresh[MAX_CITY_TILES]; /* treshholds - what city size to use a tile */
Index: common/game.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/game.c,v
retrieving revision 1.214
diff -u -u -r1.214 game.c
--- common/game.c 10 May 2005 17:27:09 -0000 1.214
+++ common/game.c 11 May 2005 13:59:25 -0000
@@ -342,6 +342,7 @@
***************************************************************/
void ruleset_data_free()
{
+ specialists_free();
techs_free();
governments_free();
nations_free();
Index: common/government.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/government.c,v
retrieving revision 1.58
diff -u -u -r1.58 government.c
--- common/government.c 10 May 2005 19:08:54 -0000 1.58
+++ common/government.c 11 May 2005 13:59:25 -0000
@@ -149,7 +149,7 @@
}
return are_reqs_active(pplayer, NULL, NULL, NULL, NULL, NULL, NULL,
- gov->req, MAX_NUM_REQS);
+ &gov->reqs);
}
/***************************************************************
@@ -186,7 +186,10 @@
game.control.government_count = num;
for (index = 0; index < num; index++) {
- governments[index].index = index;
+ struct government *gov = &governments[index];
+
+ gov->index = index;
+ requirement_vector_init(&gov->reqs);
}
}
@@ -200,6 +203,8 @@
free(gov->helptext);
gov->helptext = NULL;
+
+ requirement_vector_free(&gov->reqs);
}
/***************************************************************
Index: common/government.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/government.h,v
retrieving revision 1.45
diff -u -u -r1.45 government.h
--- common/government.h 5 May 2005 18:32:49 -0000 1.45
+++ common/government.h 11 May 2005 13:59:25 -0000
@@ -49,7 +49,7 @@
char name_orig[MAX_LEN_NAME]; /* untranslated copy */
char graphic_str[MAX_LEN_NAME];
char graphic_alt[MAX_LEN_NAME];
- struct requirement req[MAX_NUM_REQS];
+ struct requirement_vector reqs;
int ai_better; /* govt AI prefers to this one (hint) */
Index: common/improvement.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/improvement.c,v
retrieving revision 1.62
diff -u -u -r1.62 improvement.c
--- common/improvement.c 10 May 2005 19:08:54 -0000 1.62
+++ common/improvement.c 11 May 2005 13:59:25 -0000
@@ -70,10 +70,14 @@
int i;
for (i = 0; i < ARRAY_SIZE(improvement_types); i++) {
+ struct impr_type *p = get_improvement_type(i);
+
/* HACK: this field is declared const to keep anyone from changing
* them. But we have to set it somewhere! This should be the only
* place. */
- *(int *)&improvement_types[i].index = i;
+ *(int *)&p->index = i;
+
+ requirement_vector_init(&p->reqs);
}
}
@@ -86,6 +90,8 @@
free(p->helptext);
p->helptext = NULL;
+
+ requirement_vector_free(&p->reqs);
}
/***************************************************************
@@ -291,7 +297,6 @@
{
struct impr_type *impr;
bool space_part = FALSE;
- int i;
/* This also checks if tech req is Never */
if (!improvement_exists(id)) {
@@ -300,16 +305,12 @@
impr = get_improvement_type(id);
- for (i = 0; i < MAX_NUM_REQS; i++) {
- if (impr->req[i].source.type == REQ_NONE) {
- break;
- }
- if (impr->req[i].range >= REQ_RANGE_PLAYER
- && !is_req_active(p, NULL, NULL, NULL, NULL, NULL, NULL,
- &impr->req[i])) {
+ requirement_vector_iterate(&impr->reqs, preq) {
+ if (preq->range >= REQ_RANGE_PLAYER
+ && !is_req_active(p, NULL, NULL, NULL, NULL, NULL, NULL, preq)) {
return FALSE;
}
- }
+ } requirement_list_iterate_end;
/* Check for space part construction. This assumes that space parts have
* no other effects. */
@@ -371,7 +372,6 @@
bool can_player_eventually_build_improvement(const struct player *p,
Impr_type_id id)
{
- int r;
struct impr_type *building;
if (!improvement_exists(id)) {
@@ -384,17 +384,13 @@
/* Check for requirements that aren't met and that are unchanging (so
* they can never be met). */
building = get_improvement_type(id);
- for (r = 0; r < MAX_NUM_REQS; r++) {
- if (building->req[r].source.type == REQ_NONE) {
- break;
- }
- if (building->req[r].range >= REQ_RANGE_PLAYER
- && is_req_unchanging(&building->req[r])
- && !is_req_active(p, NULL, NULL, NULL, NULL, NULL, NULL,
- &building->req[r])) {
+ requirement_vector_iterate(&building->reqs, preq) {
+ if (preq->range >= REQ_RANGE_PLAYER
+ && is_req_unchanging(preq)
+ && !is_req_active(p, NULL, NULL, NULL, NULL, NULL, NULL, preq)) {
return FALSE;
}
- }
+ } requirement_list_iterate_end;
/* FIXME: should check some "unchanging" reqs here - like if there's
* a nation requirement, we can go ahead and check it now. */
Index: common/improvement.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/improvement.h,v
retrieving revision 1.47
diff -u -u -r1.47 improvement.h
--- common/improvement.h 5 May 2005 18:32:50 -0000 1.47
+++ common/improvement.h 11 May 2005 13:59:25 -0000
@@ -68,7 +68,7 @@
char name_orig[MAX_LEN_NAME]; /* untranslated */
char graphic_str[MAX_LEN_NAME]; /* city icon of improv. */
char graphic_alt[MAX_LEN_NAME]; /* city icon of improv. */
- struct requirement req[MAX_NUM_REQS];
+ struct requirement_vector reqs;
Tech_type_id obsolete_by; /* A_LAST = never obsolete */
Impr_type_id replaced_by; /* B_LAST = never replaced */
int build_cost; /* Use wrappers to access this. */
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.123
diff -u -u -r1.123 packets.def
--- common/packets.def 11 May 2005 00:13:22 -0000 1.123
+++ common/packets.def 11 May 2005 13:59:25 -0000
@@ -1049,10 +1049,11 @@
PACKET_RULESET_GAME=97;sc,lsend
UINT8 default_specialist, num_specialist_types;
UINT8 bonus_array_size; # Hack to get around limitations of packgen
- UINT8 req_array_size; # Another hack to get around limitations of packgen
STRING specialist_name[SP_MAX:num_specialist_types][MAX_LEN_NAME];
STRING specialist_short_name[SP_MAX:num_specialist_types][MAX_LEN_NAME];
- REQUIREMENT specialist_reqs[SP_MAX * MAX_NUM_REQS:req_array_size];
+ UINT16 specialist_reqs_size;
+ UINT8 specialist_reqs_count[SP_MAX:num_specialist_types];
+ REQUIREMENT specialist_reqs[SP_MAX * MAX_NUM_REQS:specialist_reqs_size];
TECH_LIST global_init_techs[MAX_NUM_TECH_LIST];
UINT8 trireme_loss_chance[MAX_VET_LEVELS];
UINT8 work_veteran_chance[MAX_VET_LEVELS];
@@ -1081,7 +1082,8 @@
PACKET_RULESET_GOVERNMENT=100;sc,lsend
GOVERNMENT id;
- REQUIREMENT reqs[MAX_NUM_REQS];
+ UINT8 reqs_count;
+ REQUIREMENT reqs[MAX_NUM_REQS:reqs_count];
UINT8 unit_happy_cost_factor;
UINT8 unit_upkeep_factor[O_MAX];
@@ -1159,7 +1161,8 @@
STRING name[MAX_LEN_NAME];
STRING citizens_graphic[MAX_LEN_NAME];
STRING citizens_graphic_alt[MAX_LEN_NAME];
- REQUIREMENT reqs[MAX_NUM_REQS];
+ UINT8 reqs_count;
+ REQUIREMENT reqs[MAX_NUM_REQS:reqs_count];
STRING graphic[MAX_LEN_NAME];
STRING graphic_alt[MAX_LEN_NAME];
SINT8 replaced_by;
@@ -1171,7 +1174,8 @@
STRING name[MAX_LEN_NAME];
STRING graphic_str[MAX_LEN_NAME];
STRING graphic_alt[MAX_LEN_NAME];
- REQUIREMENT reqs[MAX_NUM_REQS];
+ UINT8 reqs_count;
+ REQUIREMENT reqs[MAX_NUM_REQS:reqs_count];
TECH obsolete_by;
IMPROVEMENT replaced_by;
UINT16 build_cost;
Index: common/requirements.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/requirements.c,v
retrieving revision 1.24
diff -u -u -r1.24 requirements.c
--- common/requirements.c 11 May 2005 00:13:24 -0000 1.24
+++ common/requirements.c 11 May 2005 13:59:28 -0000
@@ -755,62 +755,80 @@
const struct specialist *target_specialist,
const struct requirement *req)
{
+ bool eval = FALSE;
+
/* Note the target may actually not exist. In particular, effects that
* have a REQ_SPECIAL or REQ_TERRAIN may often be passed to this function
* with a city as their target. In this case the requirement is simply
* not met. */
switch (req->source.type) {
case REQ_NONE:
- return TRUE;
+ eval = TRUE;
+ break;
case REQ_TECH:
/* The requirement is filled if the player owns the tech. */
- return is_tech_in_range(target_player, req->range,
+ eval = is_tech_in_range(target_player, req->range,
req->source.value.tech);
+ break;
case REQ_GOV:
/* The requirement is filled if the player is using the government. */
- return (target_player
+ eval = (target_player
&& (target_player->government == req->source.value.gov));
+ break;
case REQ_BUILDING:
/* The requirement is filled if there's at least one of the building
* in the city. (This is a slightly nonstandard use of
* count_sources_in_range.) */
- return (count_buildings_in_range(target_player, target_city,
+ eval = (count_buildings_in_range(target_player, target_city,
target_building,
req->range, req->survives,
req->source.value.building) > 0);
+ break;
case REQ_SPECIAL:
- return is_special_in_range(target_tile,
+ eval = is_special_in_range(target_tile,
req->range, req->survives,
req->source.value.special);
+ break;
case REQ_TERRAIN:
- return is_terrain_in_range(target_tile,
+ eval = is_terrain_in_range(target_tile,
req->range, req->survives,
req->source.value.terrain);
+ break;
case REQ_NATION:
- return is_nation_in_range(target_player, req->range, req->survives,
+ eval = is_nation_in_range(target_player, req->range, req->survives,
req->source.value.nation);
+ break;
case REQ_UNITTYPE:
- return is_unittype_in_range(target_unit,
+ eval = is_unittype_in_range(target_unit,
req->range, req->survives,
req->source.value.unittype);
+ break;
case REQ_UNITFLAG:
- return is_unitflag_in_range(target_unit,
+ eval = is_unitflag_in_range(target_unit,
req->range, req->survives,
req->source.value.unitflag);
+ break;
case REQ_OUTPUTTYPE:
- return (target_output
+ eval = (target_output
&& target_output->index == req->source.value.outputtype);
+ break;
case REQ_SPECIALIST:
- return (target_specialist
+ eval = (target_specialist
&& target_specialist->index == req->source.value.specialist);
+ break;
case REQ_MINSIZE:
- return target_city && target_city->size >= req->source.value.minsize;
- case REQ_LAST:
+ eval = target_city && target_city->size >= req->source.value.minsize;
break;
+ case REQ_LAST:
+ assert(0);
+ return FALSE;
}
- assert(0);
- return FALSE;
+ if (req->negated) {
+ return !eval;
+ } else {
+ return eval;
+ }
}
/****************************************************************************
@@ -819,9 +837,8 @@
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.
+ reqs gives the requirement vector.
+ 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
@@ -834,21 +851,16 @@
const struct unit *target_unit,
const struct output_type *target_output,
const struct specialist *target_specialist,
- const struct requirement *reqs, int num_reqs)
+ const struct requirement_vector *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_player, target_city, target_building,
- target_tile, target_unit, target_output,
- target_specialist,
- &reqs[i])) {
+ requirement_vector_iterate(reqs, preq) {
+ if (!is_req_active(target_player, target_city, target_building,
+ target_tile, target_unit, target_output,
+ target_specialist,
+ preq)) {
return FALSE;
}
- }
-
+ } requirement_list_iterate_end;
return TRUE;
}
Index: common/requirements.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/requirements.h,v
retrieving revision 1.18
diff -u -u -r1.18 requirements.h
--- common/requirements.h 11 May 2005 00:13:24 -0000 1.18
+++ common/requirements.h 11 May 2005 13:59:28 -0000
@@ -127,7 +127,7 @@
const struct unit *target_unit,
const struct output_type *target_output,
const struct specialist *target_specialist,
- const struct requirement *reqs, int num_reqs);
+ const struct requirement_vector *reqs);
bool is_req_unchanging(const struct requirement *req);
Index: common/specialist.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/specialist.c,v
retrieving revision 1.2
diff -u -u -r1.2 specialist.c
--- common/specialist.c 10 May 2005 19:08:55 -0000 1.2
+++ common/specialist.c 11 May 2005 13:59:28 -0000
@@ -31,7 +31,25 @@
int i;
for (i = 0; i < ARRAY_SIZE(specialists); i++) {
- specialists[i].index = i;
+ struct specialist *p = &specialists[i];
+
+ p->index = i;
+
+ requirement_vector_init(&p->reqs);
+ }
+}
+
+/****************************************************************************
+ Free data for specialists.
+****************************************************************************/
+void specialists_free(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(specialists); i++) {
+ struct specialist *p = &specialists[i];
+
+ requirement_vector_free(&p->reqs);
}
}
Index: common/specialist.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/specialist.h,v
retrieving revision 1.2
diff -u -u -r1.2 specialist.h
--- common/specialist.h 10 May 2005 19:08:55 -0000 1.2
+++ common/specialist.h 11 May 2005 13:59:28 -0000
@@ -23,7 +23,7 @@
int index;
char name[MAX_LEN_NAME];
char short_name[MAX_LEN_NAME];
- struct requirement req[MAX_NUM_REQS];
+ struct requirement_vector reqs;
};
#define SP_COUNT num_specialist_types
@@ -34,6 +34,7 @@
extern int default_specialist;
void specialists_init(void);
+void specialists_free(void);
struct specialist *get_specialist(Specialist_type_id spec);
Specialist_type_id find_specialist_by_name(const char *name);
Index: manual/civmanual.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/manual/civmanual.c,v
retrieving revision 1.11
diff -u -u -r1.11 civmanual.c
--- manual/civmanual.c 14 Apr 2005 04:49:15 -0000 1.11
+++ manual/civmanual.c 11 May 2005 13:59:29 -0000
@@ -110,7 +110,7 @@
load_rulesets();
for (manuals = 0; manuals < MANUAL_COUNT; manuals++) {
- int i, r;
+ int i;
my_snprintf(filename, sizeof(filename), "manual%d.html", manuals + 1);
@@ -306,15 +306,14 @@
fprintf(doc, "<table>\n");
fprintf(doc, _("<tr><td>Cost: <td>%d</tr>\n"), pimpr->build_cost);
fprintf(doc, _("<tr><td>Upkeep: <td>%d</tr>\n"), pimpr->upkeep);
- for (r = 0; r < MAX_NUM_REQS; r++) {
- struct requirement *req = pimpr->req + r;
+ requirement_vector_iterate(&pimpr->reqs, req) {
char text[512];
if (req->source.type != REQ_NONE) {
fprintf(doc, _("<tr><td>Requires: <td>%s</tr>\n"),
get_req_source_text(&req->source, text, sizeof(text)));
}
- }
+ } requirement_vector_iterate_end;
if (tech_exists(pimpr->obsolete_by)) {
fprintf(doc, _("<tr><td>Obsoleted by: <td>%s</tr>\n"),
advances[pimpr->obsolete_by].name);
Index: server/citytools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/citytools.c,v
retrieving revision 1.326
diff -u -u -r1.326 citytools.c
--- server/citytools.c 10 May 2005 19:08:55 -0000 1.326
+++ server/citytools.c 11 May 2005 13:59:31 -0000
@@ -2063,19 +2063,15 @@
/* Sell all buildings (but not Wonders) that must be next to the ocean */
built_impr_iterate(pcity, impr) {
- int r;
-
if (!can_city_sell_building(pcity, impr)) {
continue;
}
- for (r = 0; r < MAX_NUM_REQS; r++) {
- struct requirement *req = &get_improvement_type(impr)->req[r];
-
- if (req->source.type == REQ_TERRAIN
+ requirement_vector_iterate(&get_improvement_type(impr)->reqs, preq) {
+ if (preq->source.type == REQ_TERRAIN
&& !is_req_active(city_owner(pcity), pcity, NULL,
NULL, NULL, NULL, NULL,
- req)) {
+ preq)) {
do_sell_building(pplayer, pcity, impr);
notify_player_ex(pplayer, tile1, E_IMP_SOLD,
_("You sell %s in %s (now landlocked)"
@@ -2083,7 +2079,7 @@
get_improvement_name(impr), pcity->name,
impr_sell_gold(impr));
}
- }
+ } requirement_list_iterate_end;
} built_impr_iterate_end;
}
} adjc_iterate_end;
Index: server/cityturn.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/cityturn.c,v
retrieving revision 1.315
diff -u -u -r1.315 cityturn.c
--- server/cityturn.c 10 May 2005 19:08:56 -0000 1.315
+++ server/cityturn.c 11 May 2005 13:59:31 -0000
@@ -686,21 +686,15 @@
/* Maybe this improvement has been obsoleted by something that
we can build. */
if (new_target == target) {
- int j;
struct impr_type *building = get_improvement_type(target);
bool known = FALSE;
/* Nope, no use. *sigh* */
- for (j = 0; j < MAX_NUM_REQS; j++) {
- struct requirement *req = &building->req[j];
-
- if (req->source.type == REQ_NONE) {
- break;
- }
+ requirement_vector_iterate(&building->reqs, preq) {
if (!is_req_active(pplayer, pcity, NULL, NULL, NULL, NULL, NULL,
- req)) {
+ preq)) {
known = TRUE;
- switch (req->source.type) {
+ switch (preq->source.type) {
case REQ_TECH:
notify_player_ex(pplayer, pcity->tile, E_CITY_CANTBUILD,
_("%s can't build %s from the worklist; "
@@ -708,7 +702,7 @@
pcity->name,
get_impr_name_ex(pcity, target),
get_tech_name(pplayer,
- req->source.value.tech));
+ preq->source.value.tech));
break;
case REQ_BUILDING:
notify_player_ex(pplayer, pcity->tile, E_CITY_CANTBUILD,
@@ -717,7 +711,7 @@
pcity->name,
get_impr_name_ex(pcity, target),
get_impr_name_ex(pcity,
- req->source.value.building));
+ preq->source.value.building));
break;
case REQ_GOV:
notify_player_ex(pplayer, pcity->tile, E_CITY_CANTBUILD,
@@ -725,7 +719,7 @@
"it needs %s government. Postponing..."),
pcity->name,
get_impr_name_ex(pcity, target),
- get_government_name(req->source.value.gov));
+ get_government_name(preq->source.value.gov));
break;
case REQ_SPECIAL:
notify_player_ex(pplayer, pcity->tile, E_CITY_CANTBUILD,
@@ -733,7 +727,7 @@
"%s special is required. Postponing..."),
pcity->name,
get_impr_name_ex(pcity, target),
- get_special_name(req->source.value.special));
+ get_special_name(preq->source.value.special));
break;
case REQ_TERRAIN:
notify_player_ex(pplayer, pcity->tile, E_CITY_CANTBUILD,
@@ -741,7 +735,7 @@
"%s terrain is required. Postponing..."),
pcity->name,
get_impr_name_ex(pcity, target),
- get_terrain_name(req->source.value.terrain));
+ get_terrain_name(preq->source.value.terrain));
break;
case REQ_NATION:
/* FIXME: we should skip rather than postpone, since we'll
@@ -751,7 +745,7 @@
"only %s may build this. Postponing..."),
pcity->name,
get_impr_name_ex(pcity, target),
- get_nation_name(req->source.value.nation));
+ get_nation_name(preq->source.value.nation));
break;
case REQ_UNITTYPE:
case REQ_UNITFLAG:
@@ -764,7 +758,7 @@
_("%s can't build %s from the worklist; "
"city must be of size %d. Postponing..."),
pcity->name, get_impr_name_ex(pcity, target),
- req->source.value.minsize);
+ preq->source.value.minsize);
break;
case REQ_NONE:
case REQ_LAST:
@@ -773,7 +767,7 @@
}
break;
}
- }
+ } requirement_list_iterate_end;
if (!known) {
/* This shouldn't happen...
FIXME: make can_build_improvement() return a reason enum. */
Index: server/ruleset.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/ruleset.c,v
retrieving revision 1.260
diff -u -u -r1.260 ruleset.c
--- server/ruleset.c 11 May 2005 00:13:24 -0000 1.260
+++ server/ruleset.c 11 May 2005 13:59:31 -0000
@@ -1261,7 +1261,7 @@
static void load_ruleset_buildings(struct section_file *file)
{
char **sec, *item;
- int i, j, nval;
+ int i, nval;
struct impr_type *b;
const char *filename = secfile_filename(file);
@@ -1283,14 +1283,7 @@
exit(EXIT_FAILURE);
}
- for (j = 0; j < MAX_NUM_REQS; j++) {
- if (reqs->size > j) {
- b->req[j] = reqs->p[j];
- } else {
- memset(&b->req[j], 0, sizeof(b->req[j]));
- b->req[j].source.type = REQ_NONE;
- }
- }
+ requirement_vector_copy(&b->reqs, reqs);
b->obsolete_by = lookup_tech(file, sec[i], "obsolete_by",
FALSE, filename, b->name);
@@ -1649,7 +1642,7 @@
/* easy ones: */
government_iterate(g) {
- int i = g->index, j;
+ int i = g->index;
const char *waste_name[] = {NULL, "waste", "corruption",
NULL, NULL, NULL};
struct requirement_vector *reqs = lookup_req_list(file, sec[i], "reqs");
@@ -1662,14 +1655,7 @@
} else {
g->ai_better = G_MAGIC;
}
- for (j = 0; j < MAX_NUM_REQS; j++) {
- if (reqs->size > j) {
- g->req[j] = reqs->p[j];
- } else {
- g->req[j].source.type = REQ_NONE;
- memset(&g->req[j], 0, sizeof(g->req[j]));
- }
- }
+ requirement_vector_copy(&g->reqs, reqs);
sz_strlcpy(g->graphic_str,
secfile_lookup_str(file, "%s.graphic", sec[i]));
@@ -2256,7 +2242,7 @@
static void load_ruleset_cities(struct section_file *file)
{
char **styles, *replacement;
- int i, nval, j;
+ int i, nval;
const char *filename = secfile_filename(file);
char **specialist_names;
@@ -2268,7 +2254,6 @@
for (i = 0; i < nval; i++) {
const char *name = specialist_names[i], *short_name;
struct specialist *s = &specialists[i];
- int j;
struct requirement_vector *reqs;
char sub[MAX_LEN_NAME + 4];
@@ -2281,17 +2266,9 @@
my_snprintf(sub, sizeof(sub), "%s_req", name);
reqs = lookup_req_list(file, "specialist", sub);
- for (j = 0; j < MAX_NUM_REQS; j++) {
- struct requirement req = req_from_str(NULL, "", FALSE, FALSE, "");
- s->req[j] = req;
- }
-
- j = 0;
- requirement_vector_iterate(reqs, req) {
- s->req[j++] = *req;
- } requirement_vector_iterate_end;
+ requirement_vector_copy(&s->reqs, reqs);
- if (s->req[0].source.type == REQ_NONE && DEFAULT_SPECIALIST == -1) {
+ if (requirement_vector_size(&s->reqs) == 0 && DEFAULT_SPECIALIST == -1) {
DEFAULT_SPECIALIST = i;
}
}
@@ -2352,14 +2329,7 @@
"%s.citizens_graphic_alt", styles[i]));
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]));
- }
- }
+ requirement_vector_copy(&city_styles[i].reqs, reqs);
replacement = secfile_lookup_str(file, "%s.replaced_by", styles[i]);
if( strcmp(replacement, "-") == 0) {
@@ -2690,9 +2660,11 @@
sz_strlcpy(packet.name, b->name_orig);
sz_strlcpy(packet.graphic_str, b->graphic_str);
sz_strlcpy(packet.graphic_alt, b->graphic_alt);
- for (j = 0; j < MAX_NUM_REQS; j++) {
- packet.reqs[j] = b->req[j];
- }
+ j = 0;
+ requirement_vector_iterate(&b->reqs, preq) {
+ packet.reqs[j++] = *preq;
+ } requirement_vector_iterate_end;
+ packet.reqs_count = j;
packet.obsolete_by = b->obsolete_by;
packet.replaced_by = b->replaced_by;
packet.build_cost = b->build_cost;
@@ -2795,9 +2767,11 @@
/* send one packet_government */
gov.id = g->index;
- for (j = 0; j < MAX_NUM_REQS; j++) {
- gov.reqs[j] = g->req[j];
- }
+ j = 0;
+ requirement_vector_iterate(&g->reqs, preq) {
+ gov.reqs[j++] = *preq;
+ } requirement_vector_iterate_end;
+ gov.reqs_count = j;
gov.unit_happy_cost_factor = g->unit_happy_cost_factor;
gov.free_happy = g->free_happy;
@@ -2905,9 +2879,11 @@
city_p.style_id = k;
city_p.replaced_by = city_styles[k].replaced_by;
- for (j = 0; j < MAX_NUM_REQS; j++) {
- city_p.reqs[j] = city_styles[k].req[j];
- }
+ j = 0;
+ requirement_vector_iterate(&city_styles[k].reqs, preq) {
+ city_p.reqs[j++] = *preq;
+ } requirement_vector_iterate_end;
+ city_p.reqs_count = j;
sz_strlcpy(city_p.name, city_styles[k].name_orig);
sz_strlcpy(city_p.graphic, city_styles[k].graphic);
@@ -2927,11 +2903,12 @@
static void send_ruleset_game(struct conn_list *dest)
{
struct packet_ruleset_game misc_p;
+ int i;
misc_p.num_specialist_types = SP_COUNT;
misc_p.bonus_array_size = SP_COUNT * O_COUNT;
- misc_p.req_array_size = SP_COUNT * MAX_NUM_REQS;
misc_p.default_specialist = DEFAULT_SPECIALIST;
+ i = 0;
specialist_type_iterate(sp) {
struct specialist *s = get_specialist(sp);
int j;
@@ -2939,12 +2916,15 @@
sz_strlcpy(misc_p.specialist_name[sp], s->name);
sz_strlcpy(misc_p.specialist_short_name[sp], s->short_name);
- for (j = 0; j < MAX_NUM_REQS; j++) {
- int index = sp * MAX_NUM_REQS + j;
-
- misc_p.specialist_reqs[index] = s->req[j];
- }
+ j = 0;
+ requirement_vector_iterate(&s->reqs, preq) {
+ misc_p.specialist_reqs[i + j] = *preq;
+ j++;
+ } requirement_vector_iterate_end;
+ i += j;
+ misc_p.specialist_reqs_count[sp] = j;
} specialist_type_iterate_end;
+ misc_p.specialist_reqs_size = i;
memcpy(misc_p.trireme_loss_chance, game.trireme_loss_chance,
sizeof(game.trireme_loss_chance));
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Freeciv-Dev] (PR#13040) Meta-Ticket: Requirements unification,
Vasco Alexandre da Silva Costa <=
|
|