Complete.Org: Mailing Lists: Archives: freeciv-dev: May 2005:
[Freeciv-Dev] (PR#13040) Meta-Ticket: Requirements unification
Home

[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 <=