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

On 31/08/2007, Joan Creus  wrote:
>
> Anyway, implementing an
> and-list and an or-list shouldn't be too hard, and it pays off with more
> natural sentences.

 Attached patch does that. It also makes help a bit more complete and
fixes some logical errors.
 - If government is only one of the requirements, do not always list
effect as something government gives. (This should list effect with
requirement list, but until that is implemented it's better not to
claim that despotism gives +75% shield bonus (as that's only true for
city with Palace))

 This is S2_1 version. I had to touch two existing translatable strings.


 - ML

diff -Nurd -X.diff_ignore freeciv/client/helpdata.c freeciv/client/helpdata.c
--- freeciv/client/helpdata.c	2007-07-04 14:04:27.000000000 +0300
+++ freeciv/client/helpdata.c	2007-09-01 02:59:53.000000000 +0300
@@ -1282,21 +1282,112 @@
   effect_list_iterate(get_req_source_effects(&source), peffect) {
     Output_type_id output_type = O_LAST;
     struct unit_class *unitclass = NULL;
+    struct unit_type *unittype = NULL;
     enum unit_flag_id unitflag = F_LAST;
-    const char *output = "All";
+    struct astring outputs_or = ASTRING_INIT;
+    struct astring outputs_and = ASTRING_INIT;
+    bool extra_reqs = FALSE;
+
+    astr_clear(&outputs_or);
+    astr_clear(&outputs_and);
 
     /* Grab output type, if there is one */
     requirement_list_iterate(peffect->reqs, preq) {
-      if (preq->source.type == REQ_OUTPUTTYPE) {
-        output_type = preq->source.value.outputtype;
-        output = get_output_name(output_type);
-      } else if (preq->source.type == REQ_UNITCLASS) {
-        unitclass = preq->source.value.unitclass;
-      } else if (preq->source.type == REQ_UNITFLAG) {
-        unitflag = preq->source.value.unitflag;
+      switch (preq->source.type) {
+       case REQ_OUTPUTTYPE:
+         if (output_type == O_LAST) {
+           /* We should never have multiple outputtype requirements
+            * in one list in the first place (it simply makes no sense,
+            * output cannot be of multiple types)
+            * Ruleset loading code should check against that. */
+           const char *oname;
+
+           output_type = preq->source.value.outputtype;
+           oname = get_output_name(output_type);
+           astr_add(&outputs_or, oname);
+          astr_add(&outputs_and, oname);
+         }
+         break;
+       case REQ_UNITCLASS:
+         if (unitclass == NULL) {
+           unitclass = preq->source.value.unitclass;
+         }
+         break;
+       case REQ_UNITFLAG:
+         if (unitflag == F_LAST) {
+           /* FIXME: We should list all the unit flag requirements,
+            *        not only first one. */
+           unitflag = preq->source.value.unitflag;
+         }
+         break;
+       case REQ_UNITTYPE:
+         if (unittype == NULL) {
+           unittype = preq->source.value.unittype;
+         }
+         break;
+       case REQ_GOV:
+         /* This is government we are generating helptext for.
+          * ...or if not, it's ruleset bug that should never make it
+          * this far. Fix ruleset loading code. */
+         break;
+       default:
+         extra_reqs = TRUE;
+         break;
       }
     } requirement_list_iterate_end;
 
+    if (!extra_reqs) {
+      /* Only list effects that have no special requirements. */
+
+      if (output_type == O_LAST) {
+        /* There was no outputtype requirement. Effect is active for all
+         * output types. Generate lists for that. */
+        const char *prev  = NULL;
+        const char *prev2 = NULL;
+        bool harvested_only = TRUE; /* Consider only output types from fields */
+
+        if (peffect->type == EFT_UPKEEP_FACTOR
+            || peffect->type == EFT_UNIT_UPKEEP_FREE_PER_CITY
+            || peffect->type == EFT_OUTPUT_BONUS
+            || peffect->type == EFT_OUTPUT_BONUS_2) {
+          /* Effect can use or require any kind of output */
+          harvested_only = FALSE;
+        }
+
+        output_type_iterate(ot) {
+          struct output_type *pot = get_output_type(ot);
+
+          if (!harvested_only || pot->harvested) {
+            if (prev2 != NULL) {
+              astr_add(&outputs_or,  prev2);
+              astr_add(&outputs_or,  ", ");
+              astr_add(&outputs_and, prev2);
+              astr_add(&outputs_and, ", ");
+            }
+            prev2 = prev;
+            prev = _(pot->name);
+          }
+        } output_type_iterate_end;
+        if (prev2 != NULL) {
+          astr_add(&outputs_or, prev2);
+          /* TRANS: List of possible output types has this between
+           *        last two elements */
+          astr_add(&outputs_or,  Q_("?outputlist: or "));
+          astr_add(&outputs_and, prev2);
+          /* TRANS: List of possible output types has this between
+           *        last two elements */
+          astr_add(&outputs_and, Q_("?outputlist: and "));
+        }
+        if (prev != NULL) {
+          astr_add(&outputs_or, prev);
+        astr_add(&outputs_and, prev);
+        } else {
+          /* TRANS: Empty output type list, should never happen. */
+          astr_add(&outputs_or,  Q_("?outputlist: Nothing "));
+          astr_add(&outputs_and, Q_("?outputlist: Nothing "));
+        }
+      }
+
     switch (peffect->type) {
       case EFT_UNHAPPY_FACTOR:
         if (peffect->value == 1) {
@@ -1316,22 +1407,35 @@
         break;
       case EFT_UPKEEP_FACTOR:
         if (peffect->value > 1 && output_type != O_LAST) {
-          sprintf(buf + strlen(buf), _("* You pay %d times normal %s "
-                  "upkeep for your units.\n"), peffect->value, output);
+          /* TRANS: %s is always only one output type, never list */
+          sprintf(buf + strlen(buf),
+                  _("* You pay %d times normal %s upkeep for your units.\n"),
+                  peffect->value, outputs_and.str);
         } else if (peffect->value > 1) {
           sprintf(buf + strlen(buf), _("* You pay %d times normal "
                   "upkeep for your units.\n"), peffect->value);
+         } else if (peffect->value == 0 && output_type != O_LAST) {
+          /* TRANS: %s is output type */
+          sprintf(buf + strlen(buf),
+                  _("* You pay no %s upkeep for your units.\n"),
+                  outputs_and.str);
+        } else if (peffect->value == 0) {
+          /* TRANS: No upkeep of any type */
+          sprintf(buf + strlen(buf),
+                   _("* You pay no upkeep for your units.\n"));
         }
         break;
       case EFT_UNIT_UPKEEP_FREE_PER_CITY:
         if (output_type != O_LAST) {
-	  /* TRANS: %s is the output type, like 'shields' or 'gold'. There
+	  /* TRANS: %s is the output type, like 'shield' or 'gold'. There
 	   * is currently no way to control the singular/plural version of
 	   * this. */
           sprintf(buf + strlen(buf), _("* Each of your cities will avoid "
                   "paying %d %s towards unit upkeep.\n"), peffect->value, 
-                  output);
+                  outputs_and.str);
         } else {
+          /* TRANS: Amount is subtracted from upkeep cost in each upkeep
+           *        type. */
           sprintf(buf + strlen(buf), _("* Each of your cities will avoid "
                   "paying %d towards unit upkeep.\n"), peffect->value);
         }
@@ -1413,9 +1517,17 @@
         sprintf(buf + strlen(buf), _("* Has no unhappy citizens.\n"));
         break;
       case EFT_VETERAN_BUILD:
+        /* FIXME: There could be both class and flag requirement.
+         *        meaning that only some units from class are affected.
+         *          Should class related string, type related strings and
+         *        flag related string to be at least qualified to allow
+         *        different translations? */
         if (unitclass) {
           sprintf(buf + strlen(buf), _("* Veteran %s units.\n"),
                   uclass_name_translation(unitclass));
+        } else if (unittype != NULL) {
+          sprintf(buf + strlen(buf), _("* Veteran %s units.\n"),
+                  utype_name_translation(unittype));
         } else if (unitflag != F_LAST) {
           sprintf(buf + strlen(buf), _("* Veteran %s units.\n"),
                   unit_flag_rule_name(unitflag));
@@ -1424,46 +1536,67 @@
         }
         break;
       case EFT_OUTPUT_PENALTY_TILE:
+        /* TRANS: %s is list of output types, with 'or' */
         sprintf(buf + strlen(buf), _("* Each worked tile that gives more "
                 "than %d %s will suffer a -1 penalty when not "
-                "celebrating.\n"), peffect->value, output);
+                "celebrating.\n"), peffect->value, outputs_or.str);
         break;
       case EFT_OUTPUT_INC_TILE_CELEBRATE:
+        /* TRANS: %s is list of output types, with 'or' */
         sprintf(buf + strlen(buf), _("* Each worked tile with at least 1 "
-                "%s will yield %d additional %s when celebrating.\n"),
-                output, peffect->value, output);
+                "%s will yield %d more it when celebrating.\n"),
+                outputs_or.str, peffect->value);
         break;
       case EFT_OUTPUT_INC_TILE:
+        /* TRANS: %s is list of output types, with 'or' */
         sprintf(buf + strlen(buf), _("* Each worked tile with at least 1 "
-                "%s will yield %d additional %s.\n"), output, 
-                peffect->value, output);
+                "%s will yield %d more it.\n"), outputs_or.str, 
+                peffect->value);
+        break;
+      case EFT_OUTPUT_BONUS:
+      case EFT_OUTPUT_BONUS_2:
+        /* TRANS: %s is list of output types, with 'and' */
+        sprintf(buf + strlen(buf), _("* %s production is increased %d%%.\n"),
+                outputs_and.str, peffect->value);
         break;
       case EFT_OUTPUT_WASTE:
         if (peffect->value > 30) {
+          /* TRANS: %s is list of output types, with 'and' */
           sprintf(buf + strlen(buf), _("* %s production will suffer "
-                  "massive waste.\n"), output);
+                  "massive waste.\n"), outputs_and.str);
         } else if (peffect->value >= 15) {
+          /* TRANS: %s is list of output types, with 'and' */
           sprintf(buf + strlen(buf), _("* %s production will suffer "
-                  "some waste.\n"), output);
+                  "some waste.\n"), outputs_and.str);
         } else {
+          /* TRANS: %s is list of output types, with 'and' */
           sprintf(buf + strlen(buf), _("* %s production will suffer "
-                  "a small amount of waste.\n"), output);
+                  "a small amount of waste.\n"), outputs_and.str);
         }
         break;
       case EFT_OUTPUT_WASTE_BY_DISTANCE:
         if (peffect->value >= 3) {
+          /* TRANS: %s is list of output types, with 'and' */
           sprintf(buf + strlen(buf), _("* %s waste will increase quickly "
-                  "with distance from capital.\n"), output);
+                  "with distance from capital.\n"), outputs_and.str);
         } else if (peffect->value == 2) {
+          /* TRANS: %s is list of output types, with 'and' */
           sprintf(buf + strlen(buf), _("* %s waste will increase "
-                  "with distance from capital.\n"), output);
+                  "with distance from capital.\n"), outputs_and.str);
         } else {
+          /* TRANS: %s is list of output types, with 'and' */
           sprintf(buf + strlen(buf), _("* %s waste will increase slowly "
-                  "with distance from capital.\n"), output);
+                  "with distance from capital.\n"), outputs_and.str);
         }
       default:
         break;
     }
+
+    }
+
+    astr_clear(&outputs_or);
+    astr_clear(&outputs_and);
+
   } effect_list_iterate_end;
 
   unit_type_iterate(utype) {
diff -Nurd -X.diff_ignore freeciv/common/city.c freeciv/common/city.c
--- freeciv/common/city.c	2007-08-13 22:23:46.000000000 +0300
+++ freeciv/common/city.c	2007-09-01 01:00:56.000000000 +0300
@@ -50,12 +50,12 @@
  * they're just an easy way to access information about each output type. */
 const Output_type_id num_output_types = O_LAST;
 struct output_type output_types[O_LAST] = {
-  {O_FOOD, N_("Food"), "food", UNHAPPY_PENALTY_SURPLUS},
-  {O_SHIELD, N_("Shield"), "shield", UNHAPPY_PENALTY_SURPLUS},
-  {O_TRADE, N_("Trade"), "trade", UNHAPPY_PENALTY_NONE},
-  {O_GOLD, N_("Gold"), "gold", UNHAPPY_PENALTY_ALL_PRODUCTION},
-  {O_LUXURY, N_("Luxury"), "luxury", UNHAPPY_PENALTY_NONE},
-  {O_SCIENCE, N_("Science"), "science", UNHAPPY_PENALTY_ALL_PRODUCTION}
+  {O_FOOD, N_("Food"), "food", TRUE, UNHAPPY_PENALTY_SURPLUS},
+  {O_SHIELD, N_("Shield"), "shield", TRUE, UNHAPPY_PENALTY_SURPLUS},
+  {O_TRADE, N_("Trade"), "trade", TRUE, UNHAPPY_PENALTY_NONE},
+  {O_GOLD, N_("Gold"), "gold", FALSE, UNHAPPY_PENALTY_ALL_PRODUCTION},
+  {O_LUXURY, N_("Luxury"), "luxury", FALSE, UNHAPPY_PENALTY_NONE},
+  {O_SCIENCE, N_("Science"), "science", FALSE, UNHAPPY_PENALTY_ALL_PRODUCTION}
 };
 
 /**************************************************************************
diff -Nurd -X.diff_ignore freeciv/common/city.h freeciv/common/city.h
--- freeciv/common/city.h	2007-07-04 14:04:25.000000000 +0300
+++ freeciv/common/city.h	2007-09-01 01:42:18.000000000 +0300
@@ -130,7 +130,8 @@
 struct output_type {
   int index;
   const char *name; /* Untranslated name */
-  const char *id; /* Identifier string (for rulesets, etc.) */
+  const char *id;   /* Identifier string (for rulesets, etc.) */
+  bool harvested;   /* Is this output type gathered by city workers? */
   enum output_unhappy_penalty unhappy_penalty;
 };
 
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to