Complete.Org: Mailing Lists: Archives: freeciv-dev: March 2005:
[Freeciv-Dev] (PR#12659) requirements for governments
Home

[Freeciv-Dev] (PR#12659) requirements for governments

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#12659) requirements for governments
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 25 Mar 2005 23:00:50 -0800
Reply-to: bugs@xxxxxxxxxxx

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

This patch changes governments to use requirements (instead of a single 
tech_req).  This means governments could in theory depend on the 
presence of more than one tech, or on a wonder being present, etc.

The AI code is okay but only handles tech requirements.

The EFT_ANY_GOVERNMENT cheats a little since it no longer checks if the 
target government is on our tech tree.  I think this would have to be 
written as a special case.

Only the default ruleset is updated.

I think this is ready to be committed.

-jason

Index: ai/aihand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aihand.c,v
retrieving revision 1.109
diff -u -r1.109 aihand.c
--- ai/aihand.c 21 Mar 2005 14:10:53 -0000      1.109
+++ ai/aihand.c 26 Mar 2005 06:59:55 -0000
@@ -289,7 +289,7 @@
     TIMING_LOG(LOG_DEBUG, pplayer, "Finding best government");
     government_iterate(gov) {
       int val = 0;
-      int dist;
+      int dist, i;
 
       if (gov->index == game.government_when_anarchy) {
         continue; /* pointless */
@@ -337,7 +337,16 @@
 
       val += (val * bonus) / 100;
 
-      dist = MAX(1, num_unknown_techs_for_goal(pplayer, gov->required_tech));
+      /* 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) {
+         dist += MAX(1, num_unknown_techs_for_goal(pplayer,
+                                                   req->source.value.tech));
+       }
+      }
       val = amortize(val, dist);
       ai->government_want[gov->index] = val; /* Save want */
     } government_iterate_end;
@@ -360,9 +369,21 @@
       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];
-      ai->goal.govt.req = gov->required_tech;
+
+      /* 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;
+         break;
+       }
+      }
     }
   } government_iterate_end;
   /* Goodness of the ideal gov is calculated relative to the goodness of the
Index: client/helpdata.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/helpdata.c,v
retrieving revision 1.96
diff -u -r1.96 helpdata.c
--- client/helpdata.c   14 Mar 2005 20:26:24 -0000      1.96
+++ client/helpdata.c   26 Mar 2005 06:59:55 -0000
@@ -150,6 +150,43 @@
 }
 
 /****************************************************************
+  Append text for the requirement.  Something like
+
+    "Requires the Communism technology.\n\n"
+*****************************************************************/
+static void insert_requirement(struct requirement *req,
+                              char *buf, size_t bufsz)
+{
+  switch (req->source.type) {
+  case REQ_NONE:
+    return;
+  case REQ_LAST:
+    break;
+  case REQ_TECH:
+    cat_snprintf(buf, bufsz, _("Requires the %s technology.\n\n"),
+                get_tech_name(game.player_ptr, req->source.value.tech));
+    return;
+  case REQ_GOV:
+    cat_snprintf(buf, bufsz, _("Requires the %s government.\n\n"),
+                get_government_name(req->source.value.gov));
+    return;
+  case REQ_BUILDING:
+    cat_snprintf(buf, bufsz, _("Requires the %s building.\n\n"),
+                get_improvement_name(req->source.value.building));
+    return;
+  case REQ_SPECIAL:
+    cat_snprintf(buf, bufsz, _("Requires the %s terrain special.\n\n"),
+                get_special_name(req->source.value.special));
+    return;
+  case REQ_TERRAIN:
+    cat_snprintf(buf, bufsz, _("Requires the %s terrain.\n\n"),
+                get_terrain_name(req->source.value.terrain));
+    return;
+  }
+  assert(0);
+}
+
+/****************************************************************
 ...
 *****************************************************************/
 static struct help_item *new_help_item(int type)
@@ -1033,9 +1070,15 @@
   }
 
   government_iterate(g) {
-    if (g->required_tech == i) {
-      sprintf(buf + strlen(buf), _("* Allows changing government to %s.\n"),
-             g->name);
+    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) {
+       sprintf(buf + strlen(buf), _("* Allows changing government to %s.\n"),
+               g->name);
+      }
     }
   } government_iterate_end;
   if (tech_flag(i, TF_BONUS_TECH)) {
@@ -1162,6 +1205,8 @@
 {
   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 
    * game by checking if _any_ government uses it. */
@@ -1185,9 +1230,8 @@
   if (gov->helptext[0] != '\0') {
     sprintf(buf, "%s\n\n", _(gov->helptext));
   }
-  if (gov->required_tech != A_NONE) {
-    sprintf(buf + strlen(buf), _("Requires the %s technology.\n\n"),
-            advances[gov->required_tech].name);
+  for (j = 0; j < MAX_NUM_REQS; j++) {
+    insert_requirement(gov->req + j, buf, bufsz);
   }
   if (gov->max_rate < 100 && game.rgame.changable_tax) {
     sprintf(buf + strlen(buf), 
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.482
diff -u -r1.482 packhand.c
--- client/packhand.c   26 Mar 2005 05:59:13 -0000      1.482
+++ client/packhand.c   26 Mar 2005 06:59:56 -0000
@@ -2301,6 +2301,7 @@
 void handle_ruleset_government(struct packet_ruleset_government *p)
 {
   struct government *gov;
+  int j;
 
   if (p->id < 0 || p->id >= game.government_count) {
     freelog(LOG_ERROR,
@@ -2312,7 +2313,11 @@
 
   gov->index             = p->id;
 
-  gov->required_tech     = p->required_tech;
+  for (j = 0; j < MAX_NUM_REQS; j++) {
+    gov->req[j] = req_from_values(p->req_type[j], p->req_range[j],
+                                 p->req_survives[j], p->req_value[j]);
+  }
+
   gov->max_rate          = p->max_rate;
   gov->civil_war         = p->civil_war;
   gov->martial_law_max   = p->martial_law_max;
Index: common/government.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/government.c,v
retrieving revision 1.49
diff -u -r1.49 government.c
--- common/government.c 22 Jan 2005 21:12:10 -0000      1.49
+++ common/government.c 26 Mar 2005 06:59:56 -0000
@@ -193,21 +193,20 @@
 ***************************************************************/
 bool can_change_to_government(struct player *pplayer, int government)
 {
-  int req;
+  struct government *gov = &governments[government];
 
-  assert(game.government_count > 0 &&
-        government >= 0 && government < game.government_count);
-
-  req = governments[government].required_tech;
-  if (!tech_is_available(pplayer, req)) {
-    /* If the technology doesn't "exist" or if there is no way we can
-     * ever get it, then we can't change to the gov type even if we have
-     * a wonder that would otherwise allow it. */
+  if (government < 0 || government >= game.government_count) {
+    assert(0);
     return FALSE;
-  } else {
-    return (get_invention(pplayer, req) == TECH_KNOWN
-           || get_player_bonus(pplayer, EFT_ANY_GOVERNMENT) > 0);
   }
+
+  if (get_player_bonus(pplayer, EFT_ANY_GOVERNMENT) > 0) {
+    /* Note, this may allow govs that are on someone else's "tech tree". */
+    return TRUE;
+  }
+
+  return are_reqs_active(TARGET_PLAYER, pplayer, NULL, B_LAST, NULL,
+                        gov->req, MAX_NUM_REQS);
 }
 
 /***************************************************************
Index: common/government.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/government.h,v
retrieving revision 1.39
diff -u -r1.39 government.h
--- common/government.h 21 Mar 2005 12:55:07 -0000      1.39
+++ common/government.h 26 Mar 2005 06:59:56 -0000
@@ -16,6 +16,7 @@
 #include "shared.h"
 
 #include "fc_types.h"
+#include "requirements.h"
 
 struct Sprite;                 /* opaque; client-gui specific */
 
@@ -67,7 +68,7 @@
   char  name_orig[MAX_LEN_NAME]; /* untranslated copy */
   char  graphic_str[MAX_LEN_NAME];
   char  graphic_alt[MAX_LEN_NAME];
-  int   required_tech;         /* tech required to change to this gov */
+  struct requirement req[MAX_NUM_REQS];
 
   int ai_better;               /* govt AI prefers to this one (hint) */
 
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.101
diff -u -r1.101 packets.def
--- common/packets.def  26 Mar 2005 05:59:14 -0000      1.101
+++ common/packets.def  26 Mar 2005 06:59:56 -0000
@@ -1044,7 +1044,11 @@
 PACKET_RULESET_GOVERNMENT=100;sc,lsend
   GOVERNMENT id;
 
-  UINT8 required_tech;
+  UINT8 req_type[MAX_NUM_REQS];
+  UINT8 req_range[MAX_NUM_REQS];
+  UINT8 req_value[MAX_NUM_REQS];
+  BOOL req_survives[MAX_NUM_REQS];
+
   UINT8 max_rate;
   UINT8 civil_war;
   UINT8 martial_law_max;
Index: data/default/governments.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/default/governments.ruleset,v
retrieving revision 1.28
diff -u -r1.28 governments.ruleset
--- data/default/governments.ruleset    21 Mar 2005 12:55:07 -0000      1.28
+++ data/default/governments.ruleset    26 Mar 2005 06:59:56 -0000
@@ -32,8 +32,7 @@
 ; Notes on fields:
 
 ; name        = name of this government form as seen by user 
-; tech_req    = required advance, names from techs.ruleset, or special:
-;               "None" => available from start
+; reqs        = requirements for this government (see README.effects)
 ; graphic     = tag specifing preferred graphic
 ; graphic_alt = alternate graphics tag if preferred is not found;
 ;               should be a standard tag if preferred is not;
@@ -101,7 +100,7 @@
 [government_anarchy]
 
 name        = _("Anarchy")
-tech_req    = "None"
+; No reqs
 graphic     = "gov.anarchy"
 graphic_alt = "-"
 flags       = "-"
@@ -162,7 +161,7 @@
 [government_despotism]
 
 name        = _("Despotism")
-tech_req    = "None"
+; No reqs
 graphic     = "gov.despotism"
 graphic_alt = "-"
 flags       = "-"
@@ -221,7 +220,9 @@
 [government_monarchy]
 
 name        = _("Monarchy")
-tech_req    = "Monarchy"
+reqs = { "type", "name", "range"
+         "tech", "Monarchy", "Player"
+       }
 graphic     = "gov.monarchy"
 graphic_alt = "-"
 flags       = "-"
@@ -280,7 +281,9 @@
 [government_communism]
 
 name        = _("Communism")
-tech_req    = "Communism"
+reqs = { "type", "name", "range"
+         "tech", "Communism", "Player"
+       }
 graphic     = "gov.communism"
 graphic_alt = "-"
 flags       = "Build_Veteran_Diplomats", "Inspires_Partisans"
@@ -344,7 +347,9 @@
 [government_republic]
 
 name        = _("Republic")
-tech_req    = "The Republic"
+reqs = { "type", "name", "range"
+         "tech", "The Republic", "Player"
+       }
 graphic     = "gov.republic"
 graphic_alt = "-"
 flags       = "Has_Senate", "Rapture_City_Growth"
@@ -405,7 +410,9 @@
 [government_democracy]
 
 name        = _("Democracy")
-tech_req    = "Democracy"
+reqs = { "type", "name", "range"
+         "tech", "Democracy", "Player"
+       }
 graphic     = "gov.democracy"
 graphic_alt = "-"
 flags       = "Has_Senate", "Revolution_When_Unhappy", 
Index: server/plrhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/plrhand.c,v
retrieving revision 1.361
diff -u -r1.361 plrhand.c
--- server/plrhand.c    18 Mar 2005 11:26:24 -0000      1.361
+++ server/plrhand.c    26 Mar 2005 06:59:57 -0000
@@ -271,6 +271,7 @@
   bool was_first = FALSE;
   bool had_embassy[MAX_NUM_PLAYERS];
   struct city *pcity;
+  bool can_switch[game.government_count];
 
   players_iterate(aplr) {
     had_embassy[aplr->player_no]
@@ -307,12 +308,9 @@
   }
 
   government_iterate(gov) {
-    if (tech_found == gov->required_tech) {
-      notify_player_ex(plr, NULL, E_NEW_GOVERNMENT,
-                      _("Discovery of %s makes the government form %s"
-                        " available. You may want to start a revolution."),
-                      get_tech_name(plr, tech_found), gov->name);
-    }
+    /* We do it this way so all requirements are checked, including
+     * statue-of-liberty effects. */
+    can_switch[gov->index] = can_change_to_government(plr, gov->index);
   } government_iterate_end;
 
   if (tech_flag(tech_found, TF_BONUS_TECH) && was_first) {
@@ -326,6 +324,16 @@
     upgrade_city_rails(plr, was_discovery);
   }
 
+  government_iterate(gov) {
+    if (!can_switch[gov->index]
+       && can_change_to_government(plr, gov->index)) {
+      notify_player_ex(plr, NULL, E_NEW_GOVERNMENT,
+                      _("Discovery of %s makes the government form %s"
+                        " available. You may want to start a revolution."),
+                      get_tech_name(plr, tech_found), gov->name);
+    }
+  } government_iterate_end;
+
   /* enhance vision of units inside a fortress */
   if (tech_flag(tech_found, TF_WATCHTOWER)) {
     unit_list_iterate(plr->units, punit) {
Index: server/ruleset.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/ruleset.c,v
retrieving revision 1.237
diff -u -r1.237 ruleset.c
--- server/ruleset.c    26 Mar 2005 05:59:15 -0000      1.237
+++ server/ruleset.c    26 Mar 2005 06:59:58 -0000
@@ -1631,9 +1631,10 @@
 
   /* easy ones: */
   government_iterate(g) {
-    int i = g->index;
+    int i = g->index, j;
     const char *waste_name[] = {NULL, "waste", "corruption",
                                NULL, NULL, NULL};
+    struct requirement_vector *reqs = lookup_req_list(file, sec[i], "reqs");
 
     if (section_file_lookup(file, "%s.ai_better", sec[i])) {
       char entry[100];
@@ -1643,8 +1644,14 @@
     } else {
       g->ai_better = G_MAGIC;
     }
-    g->required_tech
-      = lookup_tech(file, sec[i], "tech_req", FALSE, filename, g->name);
+    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]));
+      }
+    }
     
     sz_strlcpy(g->graphic_str,
               secfile_lookup_str(file, "%s.graphic", sec[i]));
@@ -2853,7 +2860,12 @@
     /* send one packet_government */
     gov.id                 = g->index;
 
-    gov.required_tech    = g->required_tech;
+    for (j = 0; j < MAX_NUM_REQS; j++) {
+      req_get_values(&g->req[j],
+                    &gov.req_type[j], &gov.req_range[j],
+                    &gov.req_survives[j], &gov.req_value[j]);
+    }
+
     gov.max_rate         = g->max_rate;
     gov.civil_war        = g->civil_war;
     gov.martial_law_max  = g->martial_law_max;

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