Complete.Org: Mailing Lists: Archives: freeciv-dev: January 2003:
[Freeciv-Dev] (PR#2464) patch: restrict techs by nation
Home

[Freeciv-Dev] (PR#2464) patch: restrict techs by nation

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Cc: freeciv-dev@xxxxxxxxxxx
Subject: [Freeciv-Dev] (PR#2464) patch: restrict techs by nation
From: "Per I. Mathisen via RT" <rt@xxxxxxxxxxxxxx>
Date: Tue, 28 Jan 2003 15:08:04 -0800
Reply-to: rt@xxxxxxxxxxxxxx

New patch. I've dropped my previous approach and gone for Greg's idea
instead. Now you specify a root tech which cannot be shared, and it
"contaminates" the rest of the tree, unless you explicitly stop it from
doing this. There is no more mention of nations. Now, nations must specify
root techs in init_techs.

Please read, comment and test.

  - Per

Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.277
diff -u -r1.277 packhand.c
--- client/packhand.c   27 Jan 2003 22:00:34 -0000      1.277
+++ client/packhand.c   28 Jan 2003 23:00:51 -0000
@@ -1801,10 +1801,10 @@
   sz_strlcpy(a->graphic_alt, p->graphic_alt);
   a->req[0] = p->req[0];
   a->req[1] = p->req[1];
+  a->root_req = p->root_req;
   a->flags = p->flags;
   a->preset_cost = p->preset_cost;
   a->num_reqs = p->num_reqs;
-  
   a->helptext = p->helptext;   /* pointer assignment */
   
   tilespec_setup_tech_type(p->id);
Index: client/gui-gtk/diplodlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/diplodlg.c,v
retrieving revision 1.38
diff -u -r1.38 diplodlg.c
--- client/gui-gtk/diplodlg.c   15 Nov 2002 21:24:28 -0000      1.38
+++ client/gui-gtk/diplodlg.c   28 Jan 2003 23:00:51 -0000
@@ -218,10 +218,10 @@
   int i, flag;
 
   for(i=1, flag=0; i<game.num_tech_types; i++) {
-    if(get_invention(plr0, i)==TECH_KNOWN && 
-       (get_invention(plr1, i)==TECH_UNKNOWN || 
-       get_invention(plr1, i)==TECH_REACHABLE))
-       {
+    if (get_invention(plr0, i) == TECH_KNOWN
+        && (get_invention(plr1, i) == TECH_UNKNOWN
+           || get_invention(plr1, i) == TECH_REACHABLE)
+        && tech_is_available(plr1, i)) {
          GtkWidget *item=gtk_menu_item_new_with_label(advances[i].name);
 
          gtk_menu_append(GTK_MENU(popupmenu),item);
Index: client/gui-gtk-2.0/diplodlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/diplodlg.c,v
retrieving revision 1.8
diff -u -r1.8 diplodlg.c
--- client/gui-gtk-2.0/diplodlg.c       30 Dec 2002 02:32:02 -0000      1.8
+++ client/gui-gtk-2.0/diplodlg.c       28 Jan 2003 23:00:51 -0000
@@ -216,10 +216,10 @@
   int i, flag;
 
   for(i=1, flag=0; i<game.num_tech_types; i++) {
-    if(get_invention(plr0, i)==TECH_KNOWN && 
-       (get_invention(plr1, i)==TECH_UNKNOWN || 
-       get_invention(plr1, i)==TECH_REACHABLE))
-       {
+    if (get_invention(plr0, i) == TECH_KNOWN
+        && (get_invention(plr1, i) == TECH_UNKNOWN
+           || get_invention(plr1, i) == TECH_REACHABLE)
+        && tech_is_available(plr1, i)) {
          GtkWidget *item=gtk_menu_item_new_with_label(advances[i].name);
 
          gtk_menu_append(GTK_MENU(popupmenu),item);
Index: client/gui-mui/diplodlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-mui/diplodlg.c,v
retrieving revision 1.15
diff -u -r1.15 diplodlg.c
--- client/gui-mui/diplodlg.c   11 Jan 2003 16:24:42 -0000      1.15
+++ client/gui-mui/diplodlg.c   28 Jan 2003 23:00:51 -0000
@@ -262,7 +262,10 @@
 
   for(i=1, flag=0; i<game.num_tech_types; i++)
   {
-    if(get_invention(plr0, i)==TECH_KNOWN && (get_invention(plr1, 
i)==TECH_UNKNOWN || get_invention(plr1, i)==TECH_REACHABLE))
+    if (get_invention(plr0, i) == TECH_KNOWN 
+        && (get_invention(plr1, i) == TECH_UNKNOWN
+            || get_invention(plr1, i) == TECH_REACHABLE)
+        && tech_is_available(plr1, i))
     {
       entry = MUI_MakeObject(MUIO_Menuitem,advances[i].name,NULL,0,0);
       set(entry,MUIA_UserData,i);
Index: client/gui-win32/diplodlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-win32/diplodlg.c,v
retrieving revision 1.12
diff -u -r1.12 diplodlg.c
--- client/gui-win32/diplodlg.c 17 Nov 2002 19:22:24 -0000      1.12
+++ client/gui-win32/diplodlg.c 28 Jan 2003 23:00:51 -0000
@@ -184,9 +184,10 @@
   plr1=plr?pdialog->treaty.plr0:pdialog->treaty.plr1;
   menu=CreatePopupMenu();
   for(i=1, flag=0; i<game.num_tech_types; i++) {
-    if(get_invention(plr0, i)==TECH_KNOWN && 
-       (get_invention(plr1, i)==TECH_UNKNOWN || 
-        get_invention(plr1, i)==TECH_REACHABLE)) {
+    if (get_invention(plr0, i) == TECH_KNOWN
+        && (get_invention(plr1, i) == TECH_UNKNOWN || 
+            || get_invention(plr1, i) == TECH_REACHABLE)
+        && tech_is_available(plr1, i)) {
       AppendMenu(menu,MF_STRING,ID_ADVANCES_BASE+i,advances[i].name);
       iteminfo.dwItemData=plr0->player_no*10000+plr1->player_no*100+i;
       iteminfo.fMask = MIIM_DATA;
Index: client/gui-xaw/diplodlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-xaw/diplodlg.c,v
retrieving revision 1.34
diff -u -r1.34 diplodlg.c
--- client/gui-xaw/diplodlg.c   15 Nov 2002 21:24:29 -0000      1.34
+++ client/gui-xaw/diplodlg.c   28 Jan 2003 23:00:51 -0000
@@ -252,9 +252,10 @@
   int i, flag;
   
   for(i=A_FIRST, flag=0; i<game.num_tech_types; i++) {
-    if(get_invention(plr0, i)==TECH_KNOWN && 
-       (get_invention(plr1, i)==TECH_UNKNOWN || 
-       get_invention(plr1, i)==TECH_REACHABLE)) {
+    if (get_invention(plr0, i) == TECH_KNOWN
+        && (get_invention(plr1, i) == TECH_UNKNOWN
+           || get_invention(plr1, i) == TECH_REACHABLE)
+        && tech_is_available(plr1, i)) {
       Widget entry=
        XtVaCreateManagedWidget(advances[i].name, smeBSBObjectClass, 
                                popupmenu, NULL);
Index: common/capstr.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/capstr.c,v
retrieving revision 1.117
diff -u -r1.117 capstr.c
--- common/capstr.c     16 Jan 2003 18:23:35 -0000      1.117
+++ common/capstr.c     28 Jan 2003 23:00:51 -0000
@@ -75,7 +75,7 @@
  */
 
 #define CAPABILITY "+1.14.0 conn_info +occupied team tech_impr_gfx " \
-                   "city_struct_minor_cleanup"
+                   "city_struct_minor_cleanup root_tech"
   
 /* "+1.14.0" is protocol for 1.14.0 release.
  *
@@ -92,6 +92,8 @@
  *
  * "city_struct_minor_cleanup" just removes one unused variable from the
  * city struct, which no longer needs to be sent to the client.
+ *
+ * "root_tech" restricts technology transfers between players.
  */
 
 void init_our_capability(void)
Index: common/packets.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.c,v
retrieving revision 1.229
diff -u -r1.229 packets.c
--- common/packets.c    16 Jan 2003 18:23:35 -0000      1.229
+++ common/packets.c    28 Jan 2003 23:00:52 -0000
@@ -2046,6 +2046,9 @@
   dio_put_uint8(&dout, packet->id);
   dio_put_uint8(&dout, packet->req[0]);
   dio_put_uint8(&dout, packet->req[1]);
+  if (has_capability("root_tech", pc->capability)) {
+    dio_put_uint8(&dout, packet->root_req);
+  }
   dio_put_uint32(&dout, packet->flags);
   dio_put_uint32(&dout, packet->preset_cost);
   dio_put_uint32(&dout, packet->num_reqs);
@@ -2076,6 +2079,9 @@
   dio_get_uint8(&din, &packet->id);
   dio_get_uint8(&din, &packet->req[0]);
   dio_get_uint8(&din, &packet->req[1]);
+  if (has_capability("root_tech", pc->capability)) {
+    dio_get_uint8(&din, &packet->root_req);
+  }
   dio_get_uint32(&din, &packet->flags);
   dio_get_uint32(&din, &packet->preset_cost);
   dio_get_uint32(&din, &packet->num_reqs);
Index: common/packets.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.h,v
retrieving revision 1.131
diff -u -r1.131 packets.h
--- common/packets.h    16 Jan 2003 18:23:36 -0000      1.131
+++ common/packets.h    28 Jan 2003 23:00:52 -0000
@@ -15,6 +15,7 @@
 
 #include "connection.h"                /* struct connection, MAX_LEN_* */
 #include "map.h"
+#include "nation.h"
 #include "player.h"
 #include "shared.h"            /* MAX_LEN_NAME, MAX_LEN_ADDR */
 #include "spaceship.h"
@@ -634,7 +635,7 @@
 };
 
 struct packet_ruleset_tech {
-  int id, req[2];              /* indices for advances[] */
+  int id, req[2], root_req;    /* indices for advances[] */
   int flags;
   char name[MAX_LEN_NAME];
   char graphic_str[MAX_LEN_NAME];
Index: common/tech.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/tech.c,v
retrieving revision 1.56
diff -u -r1.56 tech.c
--- common/tech.c       22 Jan 2003 19:55:08 -0000      1.56
+++ common/tech.c       28 Jan 2003 23:00:52 -0000
@@ -94,7 +94,8 @@
 {
   /* The is_tech_a_req_for_goal condition is true if the tech is
    * already marked */
-  if (!tech_exists(tech) || get_invention(pplayer, tech) == TECH_KNOWN
+  if (!tech_is_available(pplayer, tech)
+      || get_invention(pplayer, tech) == TECH_KNOWN
       || is_tech_a_req_for_goal(pplayer, tech, goal)) {
     return;
   }
@@ -155,6 +156,27 @@
 }
 
 /**************************************************************************
+  Returns TRUE iff the given tech is ever reachable by the given player
+  by checking tech tree limitations.
+**************************************************************************/
+bool tech_is_available(struct player *pplayer, Tech_Type_id id)
+{
+  int root = advances[id].root_req;
+
+  if (!tech_exists(id)) {
+    return FALSE;
+  }
+
+  if (root != A_NONE && root != A_LAST
+      && get_invention(pplayer, root) != TECH_KNOWN) {
+    /* This tech requires knowledge of another tech before being 
+     * available. Prevents sharing of untransferable techs. */
+    return FALSE;
+  }
+  return TRUE;
+}
+
+/**************************************************************************
   Marks reachable techs. Calls build_required_techs to update the
   cache of requirements.
 **************************************************************************/
@@ -164,7 +186,7 @@
   enum tech_flag_id flag;
 
   for (i = 0; i < game.num_tech_types; i++) {
-    if (!tech_exists(i)) {
+    if (!tech_is_available(pplayer, i)) {
       set_invention(pplayer, i, TECH_UNKNOWN);
     } else {
       if (get_invention(pplayer, i) == TECH_REACHABLE) {
@@ -199,7 +221,8 @@
 {
   Tech_Type_id sub_goal;
 
-  if (!tech_exists(goal) || get_invention(pplayer, goal) == TECH_KNOWN) {
+  if (!tech_is_available(pplayer, goal)
+      || get_invention(pplayer, goal) == TECH_KNOWN) {
     return A_UNSET;
   }
   if (get_invention(pplayer, goal) == TECH_REACHABLE) {
@@ -221,7 +244,8 @@
 **************************************************************************/
 Tech_Type_id get_next_tech(struct player *pplayer, Tech_Type_id goal)
 {
-  if (!tech_exists(goal) || get_invention(pplayer, goal) == TECH_KNOWN) {
+  if (!tech_is_available(pplayer, goal)
+      || get_invention(pplayer, goal) == TECH_KNOWN) {
     return A_UNSET;
   }
   return (get_next_tech_rec(pplayer, goal));
Index: common/tech.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/tech.h,v
retrieving revision 1.38
diff -u -r1.38 tech.h
--- common/tech.h       13 Jan 2003 23:27:12 -0000      1.38
+++ common/tech.h       28 Jan 2003 23:00:52 -0000
@@ -15,6 +15,8 @@
 
 #include "shared.h"
 
+#include "nation.h" /* Nation_Type_id */
+
 struct player;
 
 typedef int Tech_Type_id;
@@ -75,9 +77,10 @@
 struct advance {
   char name[MAX_LEN_NAME];
   char name_orig[MAX_LEN_NAME];              /* untranslated */
-  char graphic_str[MAX_LEN_NAME];      /* which named sprite to use */
-  char graphic_alt[MAX_LEN_NAME];      /* alternate icon name */
-  int req[2];
+  char graphic_str[MAX_LEN_NAME];     /* which named sprite to use */
+  char graphic_alt[MAX_LEN_NAME];     /* alternate icon name */
+  Tech_Type_id req[2];
+  Tech_Type_id root_req;              /* A_NONE means unrestricted */
   unsigned int flags;
   char *helptext;
 
@@ -107,6 +110,7 @@
 void update_research(struct player *pplayer);
 Tech_Type_id get_next_tech(struct player *pplayer, Tech_Type_id goal);
 
+bool tech_is_available(struct player *pplayer, Tech_Type_id id);
 bool tech_exists(Tech_Type_id id);
 Tech_Type_id find_tech_by_name(const char *s);
 
Index: data/default/techs.ruleset
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/default/techs.ruleset,v
retrieving revision 1.21
diff -u -r1.21 techs.ruleset
--- data/default/techs.ruleset  3 Jan 2003 08:58:48 -0000       1.21
+++ data/default/techs.ruleset  28 Jan 2003 23:00:52 -0000
@@ -22,6 +22,9 @@
 ;
 ; name          = name as seen by user 
 ; req1, req2   = advances required before researching this one
+; root_req      = advance required before acquiring this one, inherited
+;                 by all techs that require this tech in turn unless
+;                 "None" is given explicitly
 ; flags         = special flag strings
 ; graphic       = icon for technology
 ; graphic_alt   = alternate icon
Index: server/diplhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/diplhand.c,v
retrieving revision 1.65
diff -u -r1.65 diplhand.c
--- server/diplhand.c   15 Nov 2002 21:24:30 -0000      1.65
+++ server/diplhand.c   28 Jan 2003 23:00:52 -0000
@@ -147,6 +147,16 @@
       if (pclause->from == pplayer) {
        switch(pclause->type) {
        case CLAUSE_ADVANCE:
+          if (!tech_is_available(other, pclause->value)) {
+           freelog(LOG_ERROR, "Treaty: The %s can't have tech %s",
+                    get_nation_name_plural(other->nation),
+                    advances[pclause->value].name);
+           notify_player(pplayer,
+                          _("Game: The %s can't accept %s."),
+                          get_nation_name_plural(other->nation),
+                          advances[pclause->value].name);
+           return;
+          }
          if (get_invention(pplayer, pclause->value) != TECH_KNOWN) {
            freelog(LOG_ERROR,
                     "The %s don't know tech %s, but try to give it to the %s.",
Index: server/diplomats.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/diplomats.c,v
retrieving revision 1.33
diff -u -r1.33 diplomats.c
--- server/diplomats.c  11 Dec 2002 10:39:42 -0000      1.33
+++ server/diplomats.c  28 Jan 2003 23:00:52 -0000
@@ -559,8 +559,9 @@
   /* Examine the civilization for technologies to steal. */
   count = 0;
   for (index = A_FIRST; index < game.num_tech_types; index++) {
-    if ((get_invention (pplayer, index) != TECH_KNOWN) &&
-       (get_invention (cplayer, index) == TECH_KNOWN)) {
+    if (get_invention(pplayer, index) != TECH_KNOWN
+       && get_invention(cplayer, index) == TECH_KNOWN
+        && tech_is_available(pplayer, index)) {
       count++;
     }
   }
@@ -590,8 +591,9 @@
     target = -1;
     which = myrand (count);
     for (index = A_FIRST; index < game.num_tech_types; index++) {
-      if ((get_invention (pplayer, index) != TECH_KNOWN) &&
-         (get_invention (cplayer, index) == TECH_KNOWN)) {
+      if (get_invention(pplayer, index) != TECH_KNOWN
+         && get_invention(cplayer, index) == TECH_KNOWN
+          && tech_is_available(pplayer, index)) {
        if (which > 0) {
          which--;
        } else {
Index: server/plrhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/plrhand.c,v
retrieving revision 1.257
diff -u -r1.257 plrhand.c
--- server/plrhand.c    13 Jan 2003 23:27:12 -0000      1.257
+++ server/plrhand.c    28 Jan 2003 23:00:53 -0000
@@ -127,7 +127,8 @@
   if (find_city_wonder(B_GREAT)) {
     if (pplayer->player_no==find_city_wonder(B_GREAT)->owner) {
       for (i=0;i<game.num_tech_types;i++) {
-       if (get_invention(pplayer, i)!=TECH_KNOWN 
+       if (get_invention(pplayer, i) != TECH_KNOWN
+            && tech_is_available(pplayer, i)
            && game.global_advances[i]>=2) {
          notify_player_ex(pplayer, -1, -1, E_TECH_GAIN,
                           _("Game: %s acquired from The Great Library!"),
@@ -215,6 +216,8 @@
          && get_invention(plr, tech_found) != TECH_KNOWN)
         || tech_found == A_FUTURE);
 
+  assert(tech_is_available(plr, tech_found));
+
   plr->got_tech = TRUE;
   plr->research.techs_researched++;
   was_first = (game.global_advances[tech_found] == 0);
@@ -580,8 +583,9 @@
   int i;
   int j=0;
   for (i=0;i<game.num_tech_types;i++) {
-    if (get_invention(pplayer, i)!=TECH_KNOWN && 
-       get_invention(target, i)== TECH_KNOWN) {
+    if (get_invention(pplayer, i) != TECH_KNOWN
+       && get_invention(target, i) == TECH_KNOWN
+        && tech_is_available(pplayer, i)) {
       j++;
     }
   }
@@ -598,8 +602,9 @@
     /* pick random tech */
     j = myrand(j) + 1;
     for (i = 0; i < game.num_tech_types; i++) {
-      if (get_invention(pplayer, i) != TECH_KNOWN &&
-         get_invention(target, i) == TECH_KNOWN) {
+      if (get_invention(pplayer, i) != TECH_KNOWN
+         && get_invention(target, i) == TECH_KNOWN
+          && tech_is_available(pplayer, i)) {
        j--;
       }
       if (j == 0) {
Index: server/ruleset.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/ruleset.c,v
retrieving revision 1.130
diff -u -r1.130 ruleset.c
--- server/ruleset.c    13 Jan 2003 23:27:12 -0000      1.130
+++ server/ruleset.c    28 Jan 2003 23:00:53 -0000
@@ -204,8 +204,8 @@
   char *sval;
   int i;
   
-  sval = secfile_lookup_str(file, "%s.%s", prefix, entry);
-  if (!required && strcmp(sval, "Never")==0) {
+  sval = secfile_lookup_str_default(file, NULL, "%s.%s", prefix, entry);
+  if (!sval || (!required && strcmp(sval, "Never") == 0)) {
     i = A_LAST;
   } else {
     i = find_tech_by_name(sval);
@@ -495,6 +495,7 @@
   advances[A_NONE].req[0] = A_NONE;
   advances[A_NONE].req[1] = A_NONE;
   advances[A_NONE].flags = 0;
+  advances[A_NONE].root_req = A_LAST;
 
   a = &advances[A_FIRST];
   
@@ -504,7 +505,8 @@
 
     a->req[0] = lookup_tech(file, sec[i], "req1", FALSE, filename, a->name);
     a->req[1] = lookup_tech(file, sec[i], "req2", FALSE, filename, a->name);
-    
+    a->root_req = lookup_tech(file, sec[i], "root_req", FALSE, filename, 
a->name);
+
     if ((a->req[0]==A_LAST && a->req[1]!=A_LAST) ||
        (a->req[0]!=A_LAST && a->req[1]==A_LAST)) {
       freelog(LOG_ERROR, "for tech %s: \"Never\" with non-\"Never\" (%s)",
@@ -550,6 +552,22 @@
     a++;
   }
 
+  /* Propagate a root tech up into the tech tree */
+  for(i = A_FIRST; i < num_techs; i++) {
+    a = &advances[i];
+    if (a->root_req != A_LAST && tech_exists(i)) {
+      int j;
+
+      for(j = 0; j < num_techs; j++) {
+        a = &advances[j];
+        if ((a->req[0] == i || a->req[1] == i) && a->root_req == A_LAST) {
+          a->root_req = i;
+freelog(LOG_NORMAL, "Spreading %d's contagion to %s(%d)", i, a->name, j);
+        }
+      }
+    }
+  }
+
   /* Some more consistency checking: 
      Non-removed techs depending on removed techs is too
      broken to fix by default, so die.
@@ -2448,6 +2466,7 @@
     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;
     packet.flags = a->flags;
     packet.preset_cost = a->preset_cost;
     packet.num_reqs = a->num_reqs;
Index: server/unittools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/unittools.c,v
retrieving revision 1.207
diff -u -r1.207 unittools.c
--- server/unittools.c  27 Jan 2003 19:34:53 -0000      1.207
+++ server/unittools.c  28 Jan 2003 23:00:53 -0000
@@ -1253,7 +1253,7 @@
   if requirements to make partisans when a city is conquered is fullfilled
   this routine makes a lot of partisans based on the city's size.
   To be candidate for partisans the following things must be satisfied:
-  1) Guerilla warfare must be known by atleast 1 player
+  1) The tech requirement for guerilla warfare must exist in the ruleset.
   2) The owner of the city is the original player.
   3) The player must know about communism and gunpowder
   4) the player must run either a democracy or a communist society.

Attachment: nationrestrict4-proof.tar.gz
Description: nationrestrict4-proof.tar.gz


[Prev in Thread] Current Thread [Next in Thread]