Complete.Org: Mailing Lists: Archives: freeciv-dev: April 2005:
[Freeciv-Dev] (PR#12772) requirements for buildings
Home

[Freeciv-Dev] (PR#12772) requirements for buildings

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#12772) requirements for buildings
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 11 Apr 2005 20:24:27 -0700
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=12772 >

This patch adds requirements for buildings (not to be confused with 
building requirements).

* The tech_req and bldg_req are removed.
* In their place is an array of requirements.
* AI and helptext code is updated to be as good as it is now (leaving 
much room for improvement).
* Default ruleset (only) is updated.  I'll update the others but it is 
very tedious.

In many places the changes are simple but tedious.  In a few places the 
new code makes my head hurt, but is very nice (see insert_allows()).

The advantage of the new code is that you can use ANY possible req for a 
building.  This should allow us to replace terr_gate, spec_gate, and 
can_space.  It will give great flexibility to modpacks since any new 
reqs we add will be provided automatically to buildings.

Helptext and AI will lag behind a little.  Both have the same sort of 
problem of recursive and reversed requirement associations.  For 
helptext (helpdata.c) I made a clever little function insert_allows() 
that builds a list of everything allowed by a source (this should be 
called from all possible sources, but for the moment I just used it to 
replace the old code for buildings).  For AI a similar (but much more 
complicated) sort of loop is probably wanted.  However for the moment 
there shouldn't be any real behavior changes to the AI.

P.S.  If you think this is complicated just wait until we have 
requirements for units and techs.

-jason

Index: ai/aitech.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aitech.c,v
retrieving revision 1.53
diff -u -r1.53 aitech.c
--- ai/aitech.c 18 Mar 2005 11:26:23 -0000      1.53
+++ ai/aitech.c 12 Apr 2005 03:17:01 -0000
@@ -217,29 +217,44 @@
   for (i = n - 1; i >= 0; i--) {
     Unit_Type_id iunit = get_role_unit(role, i);
     Tech_Type_id itech = get_unit_type(iunit)->tech_requirement;
-    Impr_Type_id iimpr = get_unit_type(iunit)->impr_requirement;
-    Tech_Type_id iimprtech = get_improvement_type(iimpr)->tech_req;
 
     if (can_build_unit(pcity, iunit)) {
       build_unit = iunit;
       break;
     } else if (can_eventually_build_unit(pcity, iunit)) {
       int cost = 0;
+      Impr_Type_id iimpr = get_unit_type(iunit)->impr_requirement;
 
       if (itech != A_LAST && get_invention(pplayer, itech) != TECH_KNOWN) {
         /* See if we want to invent this. */
         cost = total_bulbs_required_for_goal(pplayer, itech);
       }
       if (iimpr != B_LAST 
-          && get_invention(pplayer, iimprtech) != TECH_KNOWN) {
-        int imprcost = total_bulbs_required_for_goal(pplayer, iimprtech);
+          && !can_player_build_improvement_direct(pplayer, iimpr)) {
+       int j;
+       struct impr_type *building = get_improvement_type(iimpr);
 
-        if (imprcost < cost || cost == 0) {
-          /* If we already have the primary tech (cost==0), or the building's
-           * tech is cheaper, go for the building's required tech. */
-          itech = iimprtech; /* get this first */
-        }
-        cost += imprcost;
+       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;
+           int imprcost = total_bulbs_required_for_goal(pplayer, iimprtech);
+
+           if (imprcost < cost || cost == 0) {
+             /* If we already have the primary tech (cost==0),
+              * or the building's
+              * tech is cheaper, go for the building's required tech. */
+             itech = iimprtech; /* get this first */
+             cost = 0;
+           }
+           cost += imprcost;
+         }
+       }
       }
 
       if (cost < best_cost) {
Index: client/helpdata.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/helpdata.c,v
retrieving revision 1.100
diff -u -r1.100 helpdata.c
--- client/helpdata.c   11 Apr 2005 22:42:06 -0000      1.100
+++ client/helpdata.c   12 Apr 2005 03:17:02 -0000
@@ -190,6 +190,72 @@
   assert(0);
 }
 
+/****************************************************************************
+  Append text for what this requirement source allows.  Something like
+
+    "Allows Communism government (with University technology).\n\n"
+    "Allows Mfg. Plant building (with Factory building).\n\n"
+
+  This should be called to generate helptext for every possible source
+  type.  Note this doesn't handle effects but rather production
+  requirements (currently only building reqs).
+****************************************************************************/
+static void insert_allows(struct req_source *psource,
+                         char *buf, size_t bufsz)
+{
+  int r1, r2, i;
+
+  buf[0] = '\0';
+
+  /* FIXME: show other data like range and survives. */
+#define COREQ_APPEND(s)                                                        
    \
+  (coreq_buf[0] != '\0'                                                        
    \
+   ? cat_snprintf(coreq_buf, sizeof(coreq_buf),        ", %s", (s))        \
+   : sz_strlcpy(coreq_buf, (s)))
+
+
+  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;
+
+      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 (!are_req_sources_equal(psource, &coreq->source)) {
+           char buf2[512];
+
+           COREQ_APPEND(get_req_source_text(&coreq->source,
+                                            buf2, sizeof(buf2)));
+         }
+       }
+
+       /* Append other co-reqs. */
+       for (i = 0; building->terr_gate[i] != T_NONE; i++) {
+         COREQ_APPEND(get_terrain_name(building->terr_gate[i]));
+       }
+       for (i = 0; building->spec_gate[i] != S_NO_SPECIAL; i++) {
+         COREQ_APPEND(get_special_name(building->spec_gate[i]));
+       }
+
+       if (coreq_buf[0] == '\0') {
+         cat_snprintf(buf, bufsz, _("Allows %s."), building->name);
+       } else {
+         cat_snprintf(buf, bufsz, _("Allows %s (with %s)."),
+                      building->name, coreq_buf);
+       }
+       cat_snprintf(buf, bufsz, "\n");
+      }
+    }
+  } impr_type_iterate_end;
+
+#undef COREQ_APPEND
+}
+
 /****************************************************************
 ...
 *****************************************************************/
@@ -561,6 +627,8 @@
                        const char *user_text)
 {
   struct impr_type *imp;
+  struct req_source source = {.type = REQ_BUILDING,
+                             .value.building = which};
 
   assert(buf);
   buf[0] = '\0';
@@ -601,38 +669,7 @@
     cat_snprintf(buf, bufsz, "  ");
   }
 
-  impr_type_iterate(impr) {
-    const struct impr_type *b = get_improvement_type(impr);
-
-    if (improvement_exists(impr) && b->bldg_req == which) {
-      char req_buf[1024] = "";
-      int i;
-
-#define req_append(s)                                                      \
-      (req_buf[0] != '\0'                                                  \
-       ? cat_snprintf(req_buf, sizeof(req_buf),        ", %s", (s))            
    \
-       : sz_strlcpy(req_buf, (s)))
-
-      if (b->tech_req != A_NONE) {
-       req_append(get_tech_name(game.player_ptr, b->tech_req));
-      }
-
-      for (i = 0; b->terr_gate[i] != T_NONE; i++) {
-       req_append(get_terrain_name(b->terr_gate[i]));
-      }
-      for (i = 0; b->spec_gate[i] != S_NO_SPECIAL; i++) {
-       req_append(get_special_name(b->spec_gate[i]));
-      }
-#undef req_append
-
-      if (req_buf[0] != '\0') {
-       cat_snprintf(buf, bufsz, _("* Allows %s (with %s).\n"), b->name,
-                    req_buf);
-      } else {
-       cat_snprintf(buf, bufsz, _("* Allows %s.\n"), b->name);
-      }
-    }
-  } impr_type_iterate_end;
+  insert_allows(&source, buf + strlen(buf), bufsz - strlen(buf));
 
   unit_type_iterate(utype) {
     const struct unit_type *u = get_unit_type(utype);
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.487
diff -u -r1.487 packhand.c
--- client/packhand.c   10 Apr 2005 23:55:24 -0000      1.487
+++ client/packhand.c   12 Apr 2005 03:17:02 -0000
@@ -2232,8 +2232,10 @@
   b->name = b->name_orig;
   sz_strlcpy(b->graphic_str, p->graphic_str);
   sz_strlcpy(b->graphic_alt, p->graphic_alt);
-  b->tech_req = p->tech_req;
-  b->bldg_req = p->bldg_req;
+  for (i = 0; i < MAX_NUM_REQS; i++) {
+    b->req[i] = req_from_values(p->req_type[i], p->req_range[i],
+                               p->req_survives[i], p->req_value[i]);
+  }
   b->obsolete_by = p->obsolete_by;
   b->build_cost = p->build_cost;
   b->upkeep = p->upkeep;
@@ -2260,15 +2262,6 @@
       b = &improvement_types[id];
       freelog(LOG_DEBUG, "Impr: %s...",
              b->name);
-      freelog(LOG_DEBUG, "  tech_req    %2d/%s",
-             b->tech_req,
-             (b->tech_req == A_LAST) ?
-             "Never" : get_tech_name(game.player_ptr, b->tech_req));
-      freelog(LOG_DEBUG, "  bldg_req    %2d/%s",
-             b->bldg_req,
-             (b->bldg_req == B_LAST) ?
-             "None" :
-             improvement_types[b->bldg_req].name);
       freelog(LOG_DEBUG, "  terr_gate...");
       for (inx = 0; b->terr_gate[inx] != T_NONE; inx++) {
        freelog(LOG_DEBUG, "    %2d/%s",
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.45
diff -u -r1.45 helpdlg.c
--- client/gui-gtk-2.0/helpdlg.c        28 Mar 2005 16:48:40 -0000      1.45
+++ client/gui-gtk-2.0/helpdlg.c        12 Apr 2005 03:17:03 -0000
@@ -685,15 +685,22 @@
   
   if (which<game.num_impr_types) {
     struct impr_type *imp = &improvement_types[which];
+    int i;
+    char req_buf[512];
+
     sprintf(buf, "%d", impr_build_shield_cost(which));
     gtk_label_set_text(GTK_LABEL(help_ilabel[1]), buf);
     sprintf(buf, "%d", imp->upkeep);
     gtk_label_set_text(GTK_LABEL(help_ilabel[3]), buf);
-    if (imp->tech_req == A_LAST) {
-      gtk_label_set_text(GTK_LABEL(help_ilabel[5]), _("(Never)"));
-    } else {
-      gtk_label_set_text(GTK_LABEL(help_ilabel[5]),
-                        get_tech_name(game.player_ptr, imp->tech_req));
+
+    /* FIXME: this should show ranges and all the MAX_NUM_REQS reqs. 
+     * 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++) {
+      gtk_label_set_text(GTK_LABEL(help_ilabel[5 + i]),
+                        get_req_source_text(&imp->req[i].source,
+                                            req_buf, sizeof(req_buf)));
     }
 /*    create_tech_tree(help_improvement_tree, 0, imp->tech_req, 3);*/
   }
@@ -722,13 +729,20 @@
 
   if (which<game.num_impr_types) {
     struct impr_type *imp = &improvement_types[which];
+    int i;
+    char req_buf[512];
+
     sprintf(buf, "%d", impr_build_shield_cost(which));
     gtk_label_set_text(GTK_LABEL(help_wlabel[1]), buf);
-    if (imp->tech_req == A_LAST) {
-      gtk_label_set_text(GTK_LABEL(help_wlabel[3]), _("(Never)"));
-    } else {
-      gtk_label_set_text(GTK_LABEL(help_wlabel[3]),
-                        get_tech_name(game.player_ptr, imp->tech_req));
+
+    /* FIXME: this should show ranges and all the MAX_NUM_REQS reqs. 
+     * 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++) {
+      gtk_label_set_text(GTK_LABEL(help_ilabel[3 + i]),
+                        get_req_source_text(&imp->req[i].source,
+                                            req_buf, sizeof(req_buf)));
     }
     if (tech_exists(imp->obsolete_by)) {
       gtk_label_set_text(GTK_LABEL(help_wlabel[5]),
@@ -896,15 +910,27 @@
     gtk_widget_show(w);
 
     impr_type_iterate(j) {
-      if(i==improvement_types[j].tech_req) {
-        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);
-        gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 0);
-        gtk_widget_show_all(hbox);
+      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) {
+         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);
+         gtk_box_pack_start(GTK_BOX(hbox), w, FALSE, FALSE, 0);
+         gtk_widget_show_all(hbox);
+       }
       }
       if(i==improvement_types[j].obsolete_by) {
         hbox = gtk_hbox_new(FALSE, 0);
Index: common/capstr.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/capstr.c,v
retrieving revision 1.230
diff -u -r1.230 capstr.c
--- common/capstr.c     11 Apr 2005 22:42:06 -0000      1.230
+++ common/capstr.c     12 Apr 2005 03:17:03 -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.Apr.11"
+#define CAPABILITY "+Freeciv.Devel.2005.Apr.12"
 
 void init_our_capability(void)
 {
Index: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.325
diff -u -r1.325 city.c
--- common/city.c       10 Apr 2005 23:55:24 -0000      1.325
+++ common/city.c       12 Apr 2005 03:17:03 -0000
@@ -539,6 +539,7 @@
 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;
@@ -552,9 +553,14 @@
     return FALSE;
   }
 
-  if (building->bldg_req != B_LAST
-      && !city_got_building(pcity, building->bldg_req)) {
-    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, 0, NULL,
+                      &building->req[i])) {
+      return FALSE;
+    }
   }
 
   return TRUE;
Index: common/effects.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/effects.c,v
retrieving revision 1.28
diff -u -r1.28 effects.c
--- common/effects.c    11 Apr 2005 22:42:06 -0000      1.28
+++ common/effects.c    12 Apr 2005 03:17:03 -0000
@@ -835,42 +835,20 @@
 }
 
 /**************************************************************************
+  Make user-friendly text for the source.  The text is put into a user
+  buffer.
 **************************************************************************/
 void get_effect_req_text(struct effect *peffect, char *buf, size_t buf_len)
 {
   buf[0] = '\0';
 
   requirement_list_iterate(peffect->reqs, preq) {
-    struct req_source *psource = &preq->source;
-
     if (buf[0] != '\0') {
       mystrlcat(buf, "+", buf_len);
     }
 
-    switch (psource->type) {
-    case REQ_NONE:
-      break;
-    case REQ_TECH:
-      mystrlcat(buf, advances[psource->value.tech].name, buf_len);
-      break;
-    case REQ_GOV:
-      mystrlcat(buf, get_government_name(psource->value.gov), buf_len);
-      break;
-    case REQ_BUILDING:
-      mystrlcat(buf, get_improvement_name(psource->value.building), buf_len);
-      break;
-    case REQ_SPECIAL:
-      mystrlcat(buf, get_special_name(psource->value.special), buf_len);
-      break;
-    case REQ_TERRAIN:
-      mystrlcat(buf, get_terrain_name(psource->value.terrain), buf_len);
-      break;
-    case REQ_NATION:
-      mystrlcat(buf, get_nation_name(psource->value.nation), buf_len);
-      break;
-    case REQ_LAST:
-      break;
-    }
+    get_req_source_text(&preq->source,
+                       buf + strlen(buf), buf_len - strlen(buf));
   } requirement_list_iterate_end;
 }
 
Index: common/improvement.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/improvement.c,v
retrieving revision 1.52
diff -u -r1.52 improvement.c
--- common/improvement.c        9 Mar 2005 18:49:06 -0000       1.52
+++ common/improvement.c        12 Apr 2005 03:17:03 -0000
@@ -149,7 +149,7 @@
     return FALSE;
   }
 
-  return (improvement_types[id].tech_req!=A_LAST);
+  return TRUE;
 }
 
 /**************************************************************************
@@ -285,18 +285,25 @@
 {
   struct impr_type *impr;
   bool space_part = FALSE;
+  int i;
 
   /* This also checks if tech req is Never */
   if (!improvement_exists(id)) {
     return FALSE;
   }
 
-  if (!player_knows_improvement_tech(p, id)) {
-    return FALSE;
-  }
-
   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, 0, NULL, &impr->req[i])) {
+      return FALSE;
+    }
+  }
+
   /* Check for space part construction.  This assumes that space parts have
    * no other effects. */
   if (building_has_effect(id, EFT_SS_STRUCTURAL)) {
Index: common/improvement.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/improvement.h,v
retrieving revision 1.41
diff -u -r1.41 improvement.h
--- common/improvement.h        6 Apr 2005 17:36:15 -0000       1.41
+++ common/improvement.h        12 Apr 2005 03:17:03 -0000
@@ -70,8 +70,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. */
-  Tech_Type_id tech_req;               /* A_LAST = never; A_NONE = always */
-  Impr_Type_id bldg_req;               /* B_LAST = none required */
+  struct requirement req[MAX_NUM_REQS];
   Terrain_type_id *terr_gate;  /* list; T_NONE terminated */
   enum tile_special_type *spec_gate;   /* list; S_NO_SPECIAL terminated */
   Tech_Type_id obsolete_by;            /* A_LAST = never obsolete */
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.104
diff -u -r1.104 packets.def
--- common/packets.def  10 Apr 2005 23:55:25 -0000      1.104
+++ common/packets.def  12 Apr 2005 03:17:04 -0000
@@ -1148,8 +1148,12 @@
   STRING name[MAX_LEN_NAME];
   STRING graphic_str[MAX_LEN_NAME];
   STRING graphic_alt[MAX_LEN_NAME];
-  TECH tech_req, obsolete_by;
-  IMPROVEMENT bldg_req, replaced_by;
+  UINT8 req_type[MAX_NUM_REQS];
+  UINT8 req_range[MAX_NUM_REQS];
+  UINT8 req_value[MAX_NUM_REQS];
+  BOOL req_survives[MAX_NUM_REQS];
+  TECH obsolete_by;
+  IMPROVEMENT replaced_by;
   UINT16 build_cost;
   UINT8 upkeep, sabotage;
   STRING soundtag[MAX_LEN_NAME];
Index: common/player.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/player.c,v
retrieving revision 1.170
diff -u -r1.170 player.c
--- common/player.c     18 Mar 2005 11:26:24 -0000      1.170
+++ common/player.c     12 Apr 2005 03:17:04 -0000
@@ -484,22 +484,6 @@
 }
 
 /**************************************************************************
-  Each building type has one tech_req.  This function tells whether the
-  player knows it.
-**************************************************************************/
-bool player_knows_improvement_tech(const struct player *pplayer,
-                                  Impr_Type_id id)
-{
-  int t;
-
-  if (!improvement_exists(id)) {
-    return FALSE;
-  }
-  t = get_improvement_type(id)->tech_req;
-  return (get_invention(pplayer, t) == TECH_KNOWN);
-}
-
-/**************************************************************************
   AI players may have handicaps - allowing them to cheat or preventing
   them from using certain algorithms.  This function returns whether the
   player has the given handicap.  Human players are assumed to have no
Index: common/player.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/player.h,v
retrieving revision 1.142
diff -u -r1.142 player.h
--- common/player.h     18 Mar 2005 11:26:24 -0000      1.142
+++ common/player.h     12 Apr 2005 03:17:04 -0000
@@ -260,8 +260,6 @@
 
 bool player_in_city_radius(const struct player *pplayer,
                           const struct tile *ptile);
-bool player_knows_improvement_tech(const struct player *pplayer,
-                                  Impr_Type_id id);
 bool player_knows_techs_with_flag(const struct player *pplayer,
                                  enum tech_flag_id flag);
 int num_known_tech_with_flag(const struct player *pplayer,
Index: common/requirements.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/requirements.c,v
retrieving revision 1.11
diff -u -r1.11 requirements.c
--- common/requirements.c       11 Apr 2005 22:42:06 -0000      1.11
+++ common/requirements.c       12 Apr 2005 03:17:04 -0000
@@ -699,3 +699,74 @@
 
   return TRUE;
 }
+
+
+/****************************************************************************
+  Return TRUE iff the two sources are equivalent.  Note this isn't the
+  same as an == or memcmp check.
+*****************************************************************************/
+bool are_req_sources_equal(const struct req_source *psource1,
+                          const struct req_source *psource2)
+{
+  if (psource1->type != psource2->type) {
+    return FALSE;
+  }
+  switch (psource1->type) {
+  case REQ_NONE:
+    return TRUE;
+  case REQ_TECH:
+    return psource1->value.tech == psource2->value.tech;
+  case REQ_GOV:
+    return psource1->value.gov == psource2->value.gov;
+  case REQ_BUILDING:
+    return psource1->value.building == psource2->value.building;
+  case REQ_SPECIAL:
+    return psource1->value.special == psource2->value.special;
+  case REQ_TERRAIN:
+    return psource1->value.terrain == psource2->value.terrain;
+  case REQ_NATION:
+    return psource1->value.nation == psource2->value.nation;
+  case REQ_LAST:
+    break;
+  }
+  assert(0);
+  return FALSE;
+}
+
+/****************************************************************************
+  Make user-friendly text for the source.  The text is put into a user
+  buffer which is also returned.
+*****************************************************************************/
+char *get_req_source_text(const struct req_source *psource,
+                         char *buf, size_t bufsz)
+{
+  buf[0] = '\0'; /* to be safe. */
+  switch (psource->type) {
+  case REQ_NONE:
+    mystrlcat(buf, _("(none)"), bufsz);
+    break;
+  case REQ_TECH:
+    mystrlcat(buf, advances[psource->value.tech].name, bufsz);
+    break;
+  case REQ_GOV:
+    mystrlcat(buf, get_government_name(psource->value.gov), bufsz);
+    break;
+  case REQ_BUILDING:
+    mystrlcat(buf, get_improvement_name(psource->value.building), bufsz);
+    break;
+  case REQ_SPECIAL:
+    mystrlcat(buf, get_special_name(psource->value.special), bufsz);
+    break;
+  case REQ_TERRAIN:
+    mystrlcat(buf, get_terrain_name(psource->value.terrain), bufsz);
+    break;
+  case REQ_NATION:
+    mystrlcat(buf, get_nation_name(psource->value.nation), bufsz);
+    break;
+  case REQ_LAST:
+    assert(0);
+    break;
+  }
+
+  return buf;
+}
Index: common/requirements.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/requirements.h,v
retrieving revision 1.8
diff -u -r1.8 requirements.h
--- common/requirements.h       11 Apr 2005 22:42:06 -0000      1.8
+++ common/requirements.h       12 Apr 2005 03:17:04 -0000
@@ -111,4 +111,10 @@
                             enum req_range range, bool survives,
                             Impr_Type_id source);
 
+/* Req-source helper functions. */
+bool are_req_sources_equal(const struct req_source *psource1,
+                          const struct req_source *psource2);
+char *get_req_source_text(const struct req_source *psource,
+                         char *buf, size_t bufsz);
+
 #endif  /* FC__REQUIREMENTS_H */
Index: common/unittype.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/unittype.c,v
retrieving revision 1.51
diff -u -r1.51 unittype.c
--- common/unittype.c   4 Apr 2005 21:45:48 -0000       1.51
+++ common/unittype.c   12 Apr 2005 03:17:04 -0000
@@ -396,9 +396,6 @@
 **************************************************************************/
 bool can_player_build_unit_direct(const struct player *p, Unit_Type_id id)
 {
-  Impr_Type_id impr_req;
-  Tech_Type_id tech_req;
-
   CHECK_UNIT_TYPE(id);
   if (unit_type_flag(id, F_NUCLEAR)
       && !get_player_bonus(p, EFT_ENABLE_NUKE) > 0) {
@@ -432,9 +429,8 @@
   /* If the unit has a building requirement, we check to see if the player
    * can build that building.  Note that individual cities may not have
    * that building, so they still may not be able to build the unit. */
-  impr_req = unit_types[id].impr_requirement;
-  tech_req = get_improvement_type(impr_req)->tech_req;
-  if (impr_req != B_LAST && get_invention(p, tech_req) != TECH_KNOWN) {
+  if (!can_player_build_improvement_direct(p,
+                                          unit_types[id].impr_requirement)) {
     return FALSE;
   }
 
Index: data/default/buildings.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/default/buildings.ruleset,v
retrieving revision 1.67
diff -u -r1.67 buildings.ruleset
--- data/default/buildings.ruleset      24 Mar 2005 16:41:42 -0000      1.67
+++ data/default/buildings.ruleset      12 Apr 2005 03:17:05 -0000
@@ -28,11 +28,8 @@
 ; name         = name as seen by user 
 ; genus                = genus; one of:
 ;                 "GreatWonder", "SmallWonder", "Improvement", "Special".
-; tech_req     = advance required to build; special value "None"
-;                means no requirement, special value "Never"
-;                means building is never available
-; bldg_req     = another building in same city required to build;
-;                special value "None" means no requirement
+; reqs         = requirements to build the building (see effects.ruleset
+;                and README.effects for help on requirements)
 ; graphic      = icon of improvement (used in city dialog)
 ; graphic_alt  = alternate icon of improvement
 ; terr_gate    = list of terrain types, one of which on or adjacent
@@ -71,8 +68,10 @@
 [building_airport]
 name           = _("Airport")
 genus          = "Improvement"
-tech_req       = "Radio"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Radio", "Player"
+    }
 graphic        = "b.airport"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -97,8 +96,10 @@
 [building_aqueduct]
 name           = _("Aqueduct")
 genus          = "Improvement"
-tech_req       = "Construction"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Construction", "Player"
+    }
 graphic        = "b.aqueduct"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -117,8 +118,11 @@
 [building_bank]
 name           = _("Bank")
 genus          = "Improvement"
-tech_req       = "Banking"
-bldg_req       = "Marketplace"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Banking", "Player"
+      "Building", "Marketplace", "City"
+    }
 graphic        = "b.bank"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -138,8 +142,10 @@
 [building_barracks]
 name           = _("Barracks")
 genus          = "Improvement"
-tech_req       = "None"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+
+    }
 graphic        = "b.barracks"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -162,8 +168,10 @@
 [building_barracks_ii]
 name           = _("Barracks II")
 genus          = "Improvement"
-tech_req       = "Gunpowder"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Gunpowder", "Player"
+    }
 graphic        = "b.barracks"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -186,8 +194,10 @@
 [building_barracks_iii]
 name           = _("Barracks III")
 genus          = "Improvement"
-tech_req       = "Mobile Warfare"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Mobile Warfare", "Player"
+    }
 graphic        = "b.barracks"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -209,8 +219,11 @@
 [building_cathedral]
 name           = _("Cathedral")
 genus          = "Improvement"
-tech_req       = "Monotheism"
-bldg_req       = "Temple"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Monotheism", "Player"
+      "Building", "Temple", "City"
+    }
 graphic        = "b.cathedral"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -233,8 +246,10 @@
 [building_city_walls]
 name           = _("City Walls")
 genus          = "Improvement"
-tech_req       = "Masonry"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Masonry", "Player"
+    }
 graphic        = "b.city_walls"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -256,8 +271,10 @@
 [building_coastal_defense]
 name           = _("Coastal Defense")
 genus          = "Improvement"
-tech_req       = "Metallurgy"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Metallurgy", "Player"
+    }
 graphic        = "b.coastal_defense"
 graphic_alt    = "-"
 terr_gate      = "Ocean"
@@ -276,8 +293,10 @@
 [building_colosseum]
 name           = _("Colosseum")
 genus          = "Improvement"
-tech_req       = "Construction"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Construction", "Player"
+    }
 graphic        = "b.colosseum"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -298,8 +317,10 @@
 [building_courthouse]
 name           = _("Courthouse")
 genus          = "Improvement"
-tech_req       = "Code of Laws"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Code of Laws", "Player"
+    }
 graphic        = "b.courthouse"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -320,8 +341,10 @@
 [building_factory]
 name           = _("Factory")
 genus          = "Improvement"
-tech_req       = "Industrialization"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Industrialization", "Player"
+    }
 graphic        = "b.factory"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -340,8 +363,10 @@
 [building_granary]
 name           = _("Granary")
 genus          = "Improvement"
-tech_req       = "Pottery"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Pottery", "Player"
+    }
 graphic        = "b.granary"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -364,8 +389,10 @@
 [building_harbour]
 name           = _("Harbour")
 genus          = "Improvement"
-tech_req       = "Seafaring"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Seafaring", "Player"
+    }
 graphic        = "b.harbour"
 graphic_alt    = "-"
 terr_gate      = "Ocean"
@@ -384,8 +411,11 @@
 [building_hydro_plant]
 name           = _("Hydro Plant")
 genus          = "Improvement"
-tech_req       = "Electronics"
-bldg_req       = "Factory"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Electronics", "Player"
+      "Building", "Factory", "City"
+    }
 graphic        = "b.hydro_plant"
 graphic_alt    = "-"
 terr_gate      = "Mountains"
@@ -417,8 +447,10 @@
 [building_library]
 name           = _("Library")
 genus          = "Improvement"
-tech_req       = "Writing"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Writing", "Player"
+    }
 graphic        = "b.library"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -437,8 +469,10 @@
 [building_marketplace]
 name           = _("Marketplace")
 genus          = "Improvement"
-tech_req       = "Currency"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Currency", "Player"
+    }
 graphic        = "b.marketplace"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -457,8 +491,10 @@
 [building_mass_transit]
 name           = _("Mass Transit")
 genus          = "Improvement"
-tech_req       = "Mass Production"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Mass Production", "Player"
+    }
 graphic        = "b.mass_transit"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -478,8 +514,11 @@
 [building_mfg_plant]
 name           = _("Mfg. Plant")
 genus          = "Improvement"
-tech_req       = "Robotics"
-bldg_req       = "Factory"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Robotics", "Player"
+      "Building", "Factory", "City"
+    }
 graphic        = "b.mfg_plant"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -499,8 +538,11 @@
 [building_nuclear_plant]
 name           = _("Nuclear Plant")
 genus          = "Improvement"
-tech_req       = "Nuclear Power"
-bldg_req       = "Factory"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Nuclear Power", "Player"
+      "Building", "Factory", "City"
+    }
 graphic        = "b.nuclear_plant"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -533,8 +575,10 @@
 [building_offshore_platform]
 name           = _("Offshore Platform")
 genus          = "Improvement"
-tech_req       = "Miniaturization"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Miniaturization", "Player"
+    }
 graphic        = "b.offshore_platform"
 graphic_alt    = "-"
 terr_gate      = "Ocean"
@@ -553,8 +597,10 @@
 [building_palace]
 name           = _("Palace")
 genus          = "SmallWonder"
-tech_req       = "Masonry"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Masonry", "Player"
+    }
 graphic        = "b.palace"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -581,8 +627,10 @@
 [building_police_station]
 name           = _("Police Station")
 genus          = "Improvement"
-tech_req       = "Communism"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Communism", "Player"
+    }
 graphic        = "b.police_station"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -605,8 +653,10 @@
 [building_port_facility]
 name           = _("Port Facility")
 genus          = "Improvement"
-tech_req       = "Amphibious Warfare"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Amphibious Warfare", "Player"
+    }
 graphic        = "b.port_facility"
 graphic_alt    = "-"
 terr_gate      = "Ocean"
@@ -626,8 +676,11 @@
 [building_power_plant]
 name           = _("Power Plant")
 genus          = "Improvement"
-tech_req       = "Refining"
-bldg_req       = "Factory"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Refining", "Player"
+      "Building", "Factory", "City"
+    }
 graphic        = "b.power_plant"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -656,8 +709,10 @@
 [building_recycling_center]
 name           = _("Recycling Center")
 genus          = "Improvement"
-tech_req       = "Recycling"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Recycling", "Player"
+    }
 graphic        = "b.recycling_center"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -677,8 +732,11 @@
 [building_research_lab]
 name           = _("Research Lab")
 genus          = "Improvement"
-tech_req       = "Computers"
-bldg_req       = "University"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Computers", "Player"
+      "Building", "University", "City"
+    }
 graphic        = "b.research_lab"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -699,8 +757,10 @@
 [building_sam_battery]
 name           = _("SAM Battery")
 genus          = "Improvement"
-tech_req       = "Rocketry"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Rocketry", "Player"
+    }
 graphic        = "b.sam_battery"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -719,8 +779,10 @@
 [building_sdi_defense]
 name           = _("SDI Defense")
 genus          = "Improvement"
-tech_req       = "Laser"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Laser", "Player"
+    }
 graphic        = "b.sdi_defense"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -742,8 +804,11 @@
 [building_sewer_system]
 name           = _("Sewer System")
 genus          = "Improvement"
-tech_req       = "Sanitation"
-bldg_req       = "Aqueduct"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Sanitation", "Player"
+      "Building", "Aqueduct", "City"
+    }
 graphic        = "b.sewer_system"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -759,44 +824,14 @@
  required for a city to grow larger than size 8.\
 ")
 
-[building_solar_plant]
-name           = _("Solar Plant")
-genus          = "Improvement"
-tech_req       = "Never"               ; "Environmentalism"
-bldg_req       = "Factory"
-graphic        = "b.solar_plant"
-graphic_alt    = "-"
-;terr_gate     =
-;spec_gate     =
-obsolete_by    = "None"
-build_cost     = 220
-upkeep         = 4
-sabotage       = 100
-sound          = "b_solar_plant"
-sound_alt      = "b_generic"
-; /* xgettext:no-c-format */
-helptext       = _("\
-Eliminates all pollution generated by production in a city. \
- It also\
- increases the shield production of a Factory or Mfg. Plant in the\
- city: a Factory and a Solar Plant together give a 75% production\
- bonus, and a Factory, Mfg. Plant and Solar Plant together give\
- a 150% production bonus.\
-\n\n\
-A city can only have one Solar Plant, Hydro Plant, Power Plant, or\
- Nuclear Plant.\
-")
-; NOTE:
-; For Civ1/2 the first shield production number above should be 100%,
-; but the above describes current freeciv rules.
-; NOTE:
-; Not implemented.
-
 [building_space_component]
 name           = _("Space Component")
 genus          = "Special"
-tech_req       = "Plastics"
-bldg_req       = "Factory"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Plastics", "Player"
+      "Building", "Factory", "City"
+    }
 graphic        = "b.space_component"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -819,8 +854,11 @@
 [building_space_module]
 name           = _("Space Module")
 genus          = "Special"
-tech_req       = "Superconductors"
-bldg_req       = "Factory"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Superconductors", "Player"
+      "Building", "Factory", "City"
+    }
 graphic        = "b.space_modules"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -852,8 +890,11 @@
 [building_space_structural]
 name           = _("Space Structural")
 genus          = "Special"
-tech_req       = "Space Flight"
-bldg_req       = "Factory"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Space Flight", "Player"
+      "Building", "Factory", "City"
+    }
 graphic        = "b.space_structural"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -876,8 +917,11 @@
 [building_stock_exchange]
 name           = _("Stock Exchange")
 genus          = "Improvement"
-tech_req       = "Economics"
-bldg_req       = "Bank"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Economics", "Player"
+      "Building", "Bank", "City"
+    }
 graphic        = "b.stock_exchange"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -897,8 +941,10 @@
 [building_super_highways]
 name           = _("Super Highways")
 genus          = "Improvement"
-tech_req       = "Automobile"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Automobile", "Player"
+    }
 graphic        = "b.super_highways"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -920,8 +966,10 @@
 [building_supermarket]
 name           = _("Supermarket")
 genus          = "Improvement"
-tech_req       = "Refrigeration"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Refrigeration", "Player"
+    }
 graphic        = "b.supermarket"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -942,8 +990,10 @@
 [building_temple]
 name           = _("Temple")
 genus          = "Improvement"
-tech_req       = "Ceremonial Burial"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Ceremonial Burial", "Player"
+    }
 graphic        = "b.temple"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -963,8 +1013,11 @@
 [building_university]
 name           = _("University")
 genus          = "Improvement"
-tech_req       = "University"
-bldg_req       = "Library"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "University", "Player"
+      "Building", "Library", "Player"
+    }
 graphic        = "b.university"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -984,8 +1037,10 @@
 [building_apollo_program]
 name           = _("Apollo Program")
 genus          = "GreatWonder"
-tech_req       = "Space Flight"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Space Flight", "Player"
+    }
 graphic        = "b.apollo_program"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1005,8 +1060,10 @@
 [building_asmiths_trading_co]
 name           = _("A.Smith's Trading Co.")
 genus          = "GreatWonder"
-tech_req       = "Economics"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Economics", "Player"
+    }
 graphic        = "b.asmiths_trading_co"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1025,8 +1082,10 @@
 [building_colossus]
 name           = _("Colossus")
 genus          = "GreatWonder"
-tech_req       = "Bronze Working"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Bronze Working", "Player"
+    }
 graphic        = "b.colossus"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1045,8 +1104,10 @@
 [building_copernicus_observatory]
 name           = _("Copernicus' Observatory")
 genus          = "GreatWonder"
-tech_req       = "Astronomy"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Astronomy", "Player"
+    }
 graphic        = "b.copernicus_observatory"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1065,8 +1126,10 @@
 [building_cure_for_cancer]
 name           = _("Cure For Cancer")
 genus          = "GreatWonder"
-tech_req       = "Genetic Engineering"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Genetic Engineering", "Player"
+    }
 graphic        = "b.cure_for_cancer"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1087,8 +1150,10 @@
 [building_darwins_voyage]
 name           = _("Darwin's Voyage")
 genus          = "GreatWonder"
-tech_req       = "Railroad"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Railroad", "Player"
+    }
 graphic        = "b.darwins_voyage"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1108,8 +1173,10 @@
 [building_eiffel_tower]
 name           = _("Eiffel Tower")
 genus          = "GreatWonder"
-tech_req       = "Steam Engine"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Steam Engine", "Player"
+    }
 graphic        = "b.eiffel_tower"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1130,8 +1197,10 @@
 [building_great_library]
 name           = _("Great Library")
 genus          = "GreatWonder"
-tech_req       = "Literacy"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Literacy", "Player"
+    }
 graphic        = "b.great_library"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1150,8 +1219,10 @@
 [building_great_wall]
 name           = _("Great Wall")
 genus          = "GreatWonder"
-tech_req       = "Masonry"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Masonry", "Player"
+    }
 graphic        = "b.great_wall"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1172,8 +1243,10 @@
 [building_hanging_gardens]
 name           = _("Hanging Gardens")
 genus          = "GreatWonder"
-tech_req       = "Pottery"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Pottery", "Player"
+    }
 graphic        = "b.hanging_gardens"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1195,8 +1268,10 @@
 [building_hoover_dam]
 name           = _("Hoover Dam")
 genus          = "GreatWonder"
-tech_req       = "Electronics"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Electronics", "Player"
+    }
 graphic        = "b.hoover_dam"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1215,8 +1290,10 @@
 [building_isaac_newtons_college]
 name           = _("Isaac Newton's College")
 genus          = "GreatWonder"
-tech_req       = "Theory of Gravity"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Theory of Gravity", "Player"
+    }
 graphic        = "b.isaac_newtons_college"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1236,8 +1313,10 @@
 [building_js_bachs_cathedral]
 name           = _("J.S. Bach's Cathedral")
 genus          = "GreatWonder"
-tech_req       = "Theology"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Theology", "Player"
+    }
 graphic        = "b.js_bachs_cathedral"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1255,8 +1334,10 @@
 [building_king_richards_crusade]
 name           = _("King Richard's Crusade")
 genus          = "GreatWonder"
-tech_req       = "Engineering"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Engineering", "Player"
+    }
 graphic        = "b.king_richards_crusade"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1275,8 +1356,10 @@
 [building_leonardos_workshop]
 name           = _("Leonardo's Workshop")
 genus          = "GreatWonder"
-tech_req       = "Invention"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Invention", "Player"
+    }
 graphic        = "b.leonardos_workshop"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1294,8 +1377,10 @@
 [building_lighthouse]
 name           = _("Lighthouse")
 genus          = "GreatWonder"
-tech_req       = "Map Making"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Map Making", "Player"
+    }
 graphic        = "b.lighthouse"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1315,8 +1400,10 @@
 [building_magellans_expedition]
 name           = _("Magellan's Expedition")
 genus          = "GreatWonder"
-tech_req       = "Navigation"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Navigation", "Player"
+    }
 graphic        = "b.magellans_expedition"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1334,8 +1421,10 @@
 [building_manhattan_project]
 name           = _("Manhattan Project")
 genus          = "GreatWonder"
-tech_req       = "Nuclear Fission"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Nuclear Fission", "Player"
+    }
 graphic        = "b.manhattan_project"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1352,8 +1441,10 @@
 [building_marco_polos_embassy]
 name           = _("Marco Polo's Embassy")
 genus          = "GreatWonder"
-tech_req       = "Trade"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Trade", "Player"
+    }
 graphic        = "b.marco_polos_embassy"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1371,8 +1462,10 @@
 [building_michelangelos_chapel]
 name           = _("Michelangelo's Chapel")
 genus          = "GreatWonder"
-tech_req       = "Monotheism"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Monotheism", "Player"
+    }
 graphic        = "b.michelangelos_chapel"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1395,8 +1488,10 @@
 [building_oracle]
 name           = _("Oracle")
 genus          = "GreatWonder"
-tech_req       = "Mysticism"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Mysticism", "Player"
+    }
 graphic        = "b.oracle"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1414,8 +1509,10 @@
 [building_pyramids]
 name           = _("Pyramids")
 genus          = "GreatWonder"
-tech_req       = "Masonry"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Masonry", "Player"
+    }
 graphic        = "b.pyramids"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1435,8 +1532,10 @@
 [building_seti_program]
 name           = _("SETI Program")
 genus          = "GreatWonder"
-tech_req       = "Computers"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Computers", "Player"
+    }
 graphic        = "b.seti_program"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1454,8 +1553,10 @@
 [building_shakespeares_theatre]
 name           = _("Shakespeare's Theatre")
 genus          = "GreatWonder"
-tech_req       = "Medicine"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Medicine", "Player"
+    }
 graphic        = "b.shakespeares_theatre"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1473,8 +1574,10 @@
 [building_statue_of_liberty]
 name           = _("Statue of Liberty")
 genus          = "GreatWonder"
-tech_req       = "Democracy"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Democracy", "Player"
+    }
 graphic        = "b.statue_of_liberty"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1494,8 +1597,10 @@
 [building_sun_tzus_war_academy]
 name           = _("Sun Tzu's War Academy")
 genus          = "GreatWonder"
-tech_req       = "Feudalism"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Feudalism", "Player"
+    }
 graphic        = "b.sun_tzus_war_academy"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1515,8 +1620,10 @@
 [building_united_nations]
 name           = _("United Nations")
 genus          = "GreatWonder"
-tech_req       = "Communism"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Communism", "Player"
+    }
 graphic        = "b.united_nations"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1542,8 +1649,10 @@
 [building_womens_suffrage]
 name           = _("Women's Suffrage")
 genus          = "GreatWonder"
-tech_req       = "Industrialization"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+      "Tech", "Industrialization", "Player"
+    }
 graphic        = "b.womens_suffrage"
 graphic_alt    = "-"
 ;terr_gate     =
@@ -1565,15 +1674,12 @@
 ; outside a city that is causing at least one unhappiness.
 
 [building_capitalization]
-; FIXME: these are the real name/tech_req; restore when have a subordnate 
analogue
-; /* (ignore for gettext until fixed)
-;name          = _("Capitalization")
-;tech_req      = "The Corporation"
-; */
 name           = _("Coinage")
 genus          = "Special"
-tech_req       = "None"
-bldg_req       = "None"
+reqs   =
+    { "type", "name", "range"
+
+    }
 graphic        = "b.capitalization"
 graphic_alt    = "-"
 ;terr_gate     =
Index: manual/civmanual.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/manual/civmanual.c,v
retrieving revision 1.10
diff -u -r1.10 civmanual.c
--- manual/civmanual.c  26 Mar 2005 14:00:12 -0000      1.10
+++ manual/civmanual.c  12 Apr 2005 03:17:05 -0000
@@ -110,7 +110,7 @@
 
   load_rulesets();
   for (manuals = 0; manuals < MANUAL_COUNT; manuals++) {
-    int i;
+    int i, r;
 
     my_snprintf(filename, sizeof(filename), "manual%d.html", manuals + 1);
 
@@ -306,9 +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);
-       if (tech_exists(pimpr->tech_req)) {
-         fprintf(doc, _("<tr><td>Tech required: <td>%s</tr>\n"),
-                 advances[pimpr->tech_req].name);
+       for (r = 0; r < MAX_NUM_REQS; r++) {
+         struct requirement *req = pimpr->req + r;
+         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)));
+         }
        }
        if (tech_exists(pimpr->obsolete_by)) {
          fprintf(doc, _("<tr><td>Obsoleted by: <td>%s</tr>\n"),
@@ -335,9 +340,9 @@
        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);
-       if (tech_exists(pimpr->tech_req)) {
-         fprintf(doc, _("<tr><td>Tech required: <td>%s</tr>\n"),
-                 advances[pimpr->tech_req].name);
+       if (tech_exists(pimpr->obsolete_by)) {
+         fprintf(doc, _("<tr><td>Obsoleted by: <td>%s</tr>\n"),
+                 advances[pimpr->obsolete_by].name);
        }
        if (tech_exists(pimpr->obsolete_by)) {
          fprintf(doc, _("<tr><td>Obsoleted by: <td>%s</tr>\n"),
Index: server/cityturn.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/cityturn.c,v
retrieving revision 1.300
diff -u -r1.300 cityturn.c
--- server/cityturn.c   18 Mar 2005 11:26:24 -0000      1.300
+++ server/cityturn.c   12 Apr 2005 03:17:05 -0000
@@ -677,21 +677,81 @@
       /* 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*  */
-       if (!player_knows_improvement_tech(pplayer, target)) {
-         notify_player_ex(pplayer, pcity->tile, E_CITY_CANTBUILD,
-                          _("%s can't build %s from the worklist; "
-                            "tech not yet available.  Postponing..."),
-                          pcity->name,
-                          get_impr_name_ex(pcity, target));
-       } else if (improvement_types[target].bldg_req != B_LAST) {
-         notify_player_ex(pplayer, pcity->tile, E_CITY_CANTBUILD,
-                          _("%s can't build %s from the worklist; "
-                            "need to have %s first.  Postponing..."),
-                          pcity->name,
-                          get_impr_name_ex(pcity, target),
-                          get_impr_name_ex(pcity, 
improvement_types[target].bldg_req));
-       } else {
+       for (j = 0; j < MAX_NUM_REQS; j++) {
+         struct requirement *req = &building->req[j];
+
+         if (req->source.type == REQ_NONE) {
+           break;
+         }
+         if (!is_req_active(pplayer, pcity, 0, NULL, req)) {
+           known = TRUE;
+           switch (req->source.type) {
+           case REQ_TECH:
+             notify_player_ex(pplayer, pcity->tile, E_CITY_CANTBUILD,
+                              _("%s can't build %s from the worklist; "
+                                "tech %s not yet available.  Postponing..."),
+                              pcity->name,
+                              get_impr_name_ex(pcity, target),
+                              get_tech_name(pplayer,
+                                            req->source.value.tech));
+             break;
+           case REQ_BUILDING:
+             notify_player_ex(pplayer, pcity->tile, E_CITY_CANTBUILD,
+                              _("%s can't build %s from the worklist; "
+                                "need to have %s first.  Postponing..."),
+                              pcity->name,
+                              get_impr_name_ex(pcity, target),
+                              get_impr_name_ex(pcity,
+                                               req->source.value.building));
+             break;
+           case REQ_GOV:
+             notify_player_ex(pplayer, pcity->tile, E_CITY_CANTBUILD,
+                              _("%s can't build %s from the worklist; "
+                                "it needs %s government.  Postponing..."),
+                              pcity->name,
+                              get_impr_name_ex(pcity, target),
+                              get_government_name(req->source.value.gov));
+             break;
+           case REQ_SPECIAL:
+             notify_player_ex(pplayer, pcity->tile, E_CITY_CANTBUILD,
+                              _("%s can't build %s from the worklist; "
+                                "%s special is required.  Postponing..."),
+                              pcity->name,
+                              get_impr_name_ex(pcity, target),
+                              get_special_name(req->source.value.special));
+             break;
+           case REQ_TERRAIN:
+             notify_player_ex(pplayer, pcity->tile, E_CITY_CANTBUILD,
+                              _("%s can't build %s from the worklist; "
+                                "%s terrain is required.  Postponing..."),
+                              pcity->name,
+                              get_impr_name_ex(pcity, target),
+                              get_terrain_name(req->source.value.terrain));
+             break;
+           case REQ_NATION:
+             /* FIXME: we should skip rather than postpone, since we'll
+              * never be able to meet this req... */
+             notify_player_ex(pplayer, pcity->tile, E_CITY_CANTBUILD,
+                              _("%s can't build %s from the worklist; "
+                                "only %s may build this.  Postponing..."),
+                              pcity->name,
+                              get_impr_name_ex(pcity, target),
+                              get_nation_name(req->source.value.nation));
+             break;
+           case REQ_NONE:
+           case REQ_LAST:
+             assert(0);
+             break;
+           }
+           break;
+         }
+       }
+       if (!known) {
          /* This shouldn't happen...
             FIXME: make can_build_improvement() return a reason enum. */
          notify_player_ex(pplayer, pcity->tile, E_CITY_CANTBUILD,
Index: server/ruleset.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/ruleset.c,v
retrieving revision 1.242
diff -u -r1.242 ruleset.c
--- server/ruleset.c    10 Apr 2005 23:55:25 -0000      1.242
+++ server/ruleset.c    12 Apr 2005 03:17:06 -0000
@@ -1257,6 +1257,8 @@
   sec = secfile_get_secnames_prefix(file, "building_", &nval);
 
   for (i = 0; i < nval; i++) {
+    struct requirement_vector *reqs = lookup_req_list(file, sec[i], "reqs");
+
     b = &improvement_types[i];
 
     item = secfile_lookup_str(file, "%s.genus", sec[i]);
@@ -1268,9 +1270,14 @@
       exit(EXIT_FAILURE);
     }
 
-    b->tech_req = lookup_tech(file, sec[i], "tech_req", FALSE, filename, 
b->name);
-
-    b->bldg_req = lookup_impr_type(file, sec[i], "bldg_req", FALSE, filename, 
b->name);
+    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;
+      }
+    }
 
     list = secfile_lookup_str_vec(file, &count, "%s.terr_gate", sec[i]);
     b->terr_gate = fc_malloc((count + 1) * sizeof(b->terr_gate[0]));
@@ -1342,12 +1349,6 @@
   impr_type_iterate(i) {
     b = &improvement_types[i];
     if (improvement_exists(i)) {
-      if (!tech_exists(b->tech_req)) {
-       freelog(LOG_ERROR,
-               "improvement \"%s\": depends on removed tech \"%s\" (%s)",
-               b->name, advances[b->tech_req].name, filename);
-       b->tech_req = A_LAST;
-      }
       if (b->obsolete_by != A_LAST
          && (b->obsolete_by == A_NONE || !tech_exists(b->obsolete_by))) {
        freelog(LOG_ERROR,
@@ -2751,7 +2752,7 @@
     packet.id = tech_id;
     sz_strlcpy(packet.name, a->name_orig);
     sz_strlcpy(packet.graphic_str, a->graphic_str);
-    sz_strlcpy(packet.graphic_alt, a->graphic_alt);      
+    sz_strlcpy(packet.graphic_alt, a->graphic_alt);
     packet.req[0] = a->req[0];
     packet.req[1] = a->req[1];
     packet.root_req = a->root_req;
@@ -2777,14 +2778,18 @@
   impr_type_iterate(i) {
     struct impr_type *b = &improvement_types[i];
     struct packet_ruleset_building packet;
+    int j;
 
     packet.id = i;
     packet.genus = b->genus;
     sz_strlcpy(packet.name, b->name_orig);
     sz_strlcpy(packet.graphic_str, b->graphic_str);
     sz_strlcpy(packet.graphic_alt, b->graphic_alt);
-    packet.tech_req = b->tech_req;
-    packet.bldg_req = b->bldg_req;
+    for (j = 0; j < MAX_NUM_REQS; j++) {
+      req_get_values(&b->req[j],
+                    &packet.req_type[j], &packet.req_range[j],
+                    &packet.req_survives[j], &packet.req_value[j]);
+    }
     packet.obsolete_by = b->obsolete_by;
     packet.replaced_by = b->replaced_by;
     packet.build_cost = b->build_cost;

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#12772) requirements for buildings, Jason Short <=