Complete.Org: Mailing Lists: Archives: freeciv-dev: April 2003:
[Freeciv-Dev] nation restrict tech v8 (PR#2464)
Home

[Freeciv-Dev] nation restrict tech v8 (PR#2464)

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients:;
Subject: [Freeciv-Dev] nation restrict tech v8 (PR#2464)
From: "Per I. Mathisen" <per@xxxxxxxxxxx>
Date: Mon, 28 Apr 2003 17:28:47 -0700
Reply-to: rt@xxxxxxxxxxxxxx

CHANGES
 - We now only use A_NONE as void root_req.
 - We can overload inheritance. This means we don't die if a tech "has two
root techs". While this _may_ be caused by an oversight on part of the
ruleset author, it is also a feature: You can change the root_req higher
up in the tech tree.
 - Jason made the inheritance point back to previous tech instead of to
root tech (so tech3 requires tech2 requires tech1 instead of tech2 and
tech3 requires tech1), I changed it back to all require the root tech.
 - "init_tech =" option in rulesets now honoured also for savegames (I
need someone to look at this, I may have made some mistakes in savegame.c)
 - Jason's patch lost the capstr; I added a mandatory :)

I did not rewrite Jason's "quick hack" inheritance code. I thought I could
write a better recursive code, but lacking dependency information going
the right way (which depend on us instead of which we depend on), I
couldn't do it.

It should be ready for cvs now.

  - Per

Index: ai/aitech.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/ai/aitech.c,v
retrieving revision 1.38
diff -u -r1.38 aitech.c
--- ai/aitech.c 13 Jan 2003 23:27:03 -0000      1.38
+++ ai/aitech.c 29 Apr 2003 00:24:04 -0000
@@ -50,8 +50,10 @@
       && !wonder_obsolete(building)) {
     Tech_Type_id tech = improvement_types[building].tech_req;
 
-    if (tech_exists(tech) && get_invention(plr, tech) != TECH_KNOWN)
+    if (tech_is_available(plr, tech) 
+        && get_invention(plr, tech) != TECH_KNOWN) {
       return tech;
+    }
   }
   return A_UNSET;
 }
@@ -70,8 +72,10 @@
 
   for (i = 0 ; i < MAX_NUM_TECH_GOALS; i++) {
     Tech_Type_id j = prace->goals.tech[i];
-    if (!tech_exists(j) || get_invention(pplayer, j) == TECH_KNOWN) 
+    if (!tech_is_available(pplayer, j) 
+        || get_invention(pplayer, j) == TECH_KNOWN) {
       continue;
+    }
     dist = num_unknown_techs_for_goal(pplayer, j);
     if (dist < bestdist) { 
       bestdist = dist;
@@ -154,11 +158,18 @@
     } else goal_values[i] = 0;
   }
 
-  l = A_UNSET;
-  k = A_UNSET;
+  l = A_UNSET; /* currently researched tech */
+  k = A_UNSET; /* current tech goal */
   for (i = A_FIRST; i < game.num_tech_types; i++) {
-    if (values[i] > values[l] && get_invention(pplayer, i) == TECH_REACHABLE) 
l = i;
-    if (goal_values[i] > goal_values[k]) k = i;
+    if (values[i] > values[l]
+        && tech_is_available(pplayer, i)
+        && get_invention(pplayer, i) == TECH_REACHABLE) {
+      l = i;
+    }
+    if (goal_values[i] > goal_values[k]
+        && tech_is_available(pplayer, i)) {
+      k = i;
+    }
   }
   freelog(LOG_DEBUG, "%s wants %s with desire %d (%d).", pplayer->name,
                advances[l].name, values[l], pplayer->ai.tech_want[l]);
Index: client/helpdata.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/helpdata.c,v
retrieving revision 1.60
diff -u -r1.60 helpdata.c
--- client/helpdata.c   4 Apr 2003 15:47:45 -0000       1.60
+++ client/helpdata.c   29 Apr 2003 00:24:04 -0000
@@ -785,7 +785,7 @@
              _("If we would now start with %s we would need %d bulbs."),
              advances[i].name,
              base_total_bulbs_required(game.player_ptr, i));
-    } else {
+    } else if (tech_is_available(game.player_ptr, i)) {
       sprintf(buf + strlen(buf),
              _("To reach %s we need to obtain %d other "
                "technologies first. The whole project "
@@ -793,8 +793,11 @@
              advances[i].name,
              num_unknown_techs_for_goal(game.player_ptr, i) - 1,
              total_bulbs_required_for_goal(game.player_ptr, i));
+    } else {
+      sprintf(buf + strlen(buf),
+             _("You cannot research this technology."));
     }
-    if (!techs_have_fixed_costs()) {
+    if (!techs_have_fixed_costs() && tech_is_available(game.player_ptr, i)) {
       sprintf(buf + strlen(buf),
              _(" This number may vary depending on what "
                "other players will research.\n"));
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.303
diff -u -r1.303 packhand.c
--- client/packhand.c   27 Apr 2003 14:46:27 -0000      1.303
+++ client/packhand.c   29 Apr 2003 00:24:04 -0000
@@ -1897,10 +1897,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.39
diff -u -r1.39 diplodlg.c
--- client/gui-gtk/diplodlg.c   4 Apr 2003 15:47:46 -0000       1.39
+++ client/gui-gtk/diplodlg.c   29 Apr 2003 00:24:04 -0000
@@ -219,10 +219,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/repodlgs.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/repodlgs.c,v
retrieving revision 1.70
diff -u -r1.70 repodlgs.c
--- client/gui-gtk/repodlgs.c   4 Apr 2003 15:47:47 -0000       1.70
+++ client/gui-gtk/repodlgs.c   29 Apr 2003 00:24:04 -0000
@@ -493,9 +493,10 @@
    */
   hist=0;
   for(i=A_FIRST; i<game.num_tech_types; i++) {
-    if(get_invention(game.player_ptr, i) != TECH_KNOWN &&
-       advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST &&
-       num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
+    if (tech_is_available(game.player_ptr, i)
+        && get_invention(game.player_ptr, i) != TECH_KNOWN
+        && advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST
+        && num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
       if (i==game.player_ptr->ai.tech_goal)
        hist=i;
       sorting_list = g_list_append(sorting_list, GINT_TO_POINTER(i));
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.10
diff -u -r1.10 diplodlg.c
--- client/gui-gtk-2.0/diplodlg.c       17 Apr 2003 21:18:08 -0000      1.10
+++ client/gui-gtk-2.0/diplodlg.c       29 Apr 2003 00:24:04 -0000
@@ -238,9 +238,10 @@
     menu = gtk_menu_new();
 
     for (i = 1, flag = FALSE; 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)) {
        item = gtk_menu_item_new_with_label(advances[i].name);
 
        gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
Index: client/gui-gtk-2.0/repodlgs.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/repodlgs.c,v
retrieving revision 1.28
diff -u -r1.28 repodlgs.c
--- client/gui-gtk-2.0/repodlgs.c       17 Apr 2003 21:18:08 -0000      1.28
+++ client/gui-gtk-2.0/repodlgs.c       29 Apr 2003 00:24:05 -0000
@@ -499,9 +499,10 @@
    */
   hist=0;
   for(i=A_FIRST; i<game.num_tech_types; i++) {
-    if(get_invention(game.player_ptr, i) != TECH_KNOWN &&
-       advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST &&
-       num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
+    if (tech_is_available(game.player_ptr, i)
+        && get_invention(game.player_ptr, i) != TECH_KNOWN
+        && advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST
+        && num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
       if (i==game.player_ptr->ai.tech_goal)
        hist=i;
       sorting_list = g_list_append(sorting_list, GINT_TO_POINTER(i));
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   29 Apr 2003 00:24:05 -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-mui/repodlgs.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-mui/repodlgs.c,v
retrieving revision 1.29
diff -u -r1.29 repodlgs.c
--- client/gui-mui/repodlgs.c   4 Apr 2003 15:47:47 -0000       1.29
+++ client/gui-mui/repodlgs.c   29 Apr 2003 00:24:05 -0000
@@ -240,9 +240,10 @@
 
   for (i = A_FIRST, j = 0; i < game.num_tech_types; i++)
   {
-    if (get_invention(game.player_ptr, i) != TECH_KNOWN &&
-       advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST &&
-       num_unknown_techs_for_goal(game.player_ptr, i) < 11)
+    if (tech_is_available(game.player_ptr, i)
+       && get_invention(game.player_ptr, i) != TECH_KNOWN &&
+       && advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST
+       && num_unknown_techs_for_goal(game.player_ptr, i) < 11)
       j++;
   }
   if (game.player_ptr->ai.tech_goal == A_UNSET) {
Index: client/gui-sdl/repodlgs.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-sdl/repodlgs.c,v
retrieving revision 1.14
diff -u -r1.14 repodlgs.c
--- client/gui-sdl/repodlgs.c   4 Apr 2003 15:47:48 -0000       1.14
+++ client/gui-sdl/repodlgs.c   29 Apr 2003 00:24:05 -0000
@@ -896,9 +896,10 @@
    */
   count = 0;
   for (i = A_FIRST; i < game.num_tech_types; i++) {
-    if (get_invention(game.player_ptr, i) != TECH_KNOWN &&
-       advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST &&
-       num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
+    if (tech_is_available(game.player_ptr, i)
+        && get_invention(game.player_ptr, i) != TECH_KNOWN
+        && advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST
+       && num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
 
       pStr = create_str16_from_char(advances[i].name, 10);
       pStr->style |= TTF_STYLE_BOLD;
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 29 Apr 2003 00:24:05 -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-win32/repodlgs.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-win32/repodlgs.c,v
retrieving revision 1.27
diff -u -r1.27 repodlgs.c
--- client/gui-win32/repodlgs.c 4 Apr 2003 15:47:48 -0000       1.27
+++ client/gui-win32/repodlgs.c 29 Apr 2003 00:24:05 -0000
@@ -144,9 +144,10 @@
   ComboBox_ResetContent(GetDlgItem(science_dlg,ID_SCIENCE_GOAL));
     hist=0;
   for(i=A_FIRST; i<game.num_tech_types; i++) {
-    if(get_invention(game.player_ptr, i) != TECH_KNOWN &&
-       advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST &&
-       num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
+    if (tech_is_available(game.player_ptr, i)
+        && get_invention(game.player_ptr, i) != TECH_KNOWN
+        && advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST
+        && num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
       id=ComboBox_AddString(GetDlgItem(science_dlg,ID_SCIENCE_GOAL),
                            advances[i].name);
       ComboBox_SetItemData(GetDlgItem(science_dlg,ID_SCIENCE_GOAL),
Index: client/gui-xaw/diplodlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-xaw/diplodlg.c,v
retrieving revision 1.35
diff -u -r1.35 diplodlg.c
--- client/gui-xaw/diplodlg.c   4 Apr 2003 15:47:48 -0000       1.35
+++ client/gui-xaw/diplodlg.c   29 Apr 2003 00:24:05 -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: client/gui-xaw/repodlgs.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-xaw/repodlgs.c,v
retrieving revision 1.49
diff -u -r1.49 repodlgs.c
--- client/gui-xaw/repodlgs.c   4 Apr 2003 15:47:48 -0000       1.49
+++ client/gui-xaw/repodlgs.c   29 Apr 2003 00:24:05 -0000
@@ -332,9 +332,10 @@
     XtSetSensitive(science_change_menu_button, FALSE);
   
  for(i=A_FIRST, flag=0; i<game.num_tech_types; i++)
-    if(get_invention(game.player_ptr, i) != TECH_KNOWN &&
-       advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST &&
-       num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
+    if (tech_is_available(game.player_ptr, i)
+        && get_invention(game.player_ptr, i) != TECH_KNOWN
+        && advances[i].req[0] != A_LAST && advances[i].req[1] != A_LAST
+        && num_unknown_techs_for_goal(game.player_ptr, i) < 11) {
       Widget entry=
       XtVaCreateManagedWidget(advances[i].name, smeBSBObjectClass, 
                              goalmenu, NULL);
Index: common/capstr.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/capstr.c,v
retrieving revision 1.132
diff -u -r1.132 capstr.c
--- common/capstr.c     22 Apr 2003 20:50:56 -0000      1.132
+++ common/capstr.c     29 Apr 2003 00:24:05 -0000
@@ -77,7 +77,8 @@
 #define CAPABILITY "+1.14.0 conn_info +occupied team tech_impr_gfx " \
                    "city_struct_minor_cleanup obsolete_last class_legend " \
                    "+impr_req +waste +fastfocus +continent +small_dipl " \
-                   "+no_nation_selected +diplomacy +no_extra_tiles"
+                   "+no_nation_selected +diplomacy +no_extra_tiles " \
+                   "+root_tech"
 /* "+1.14.0" is protocol for 1.14.0 release.
  *
  * "conn_info" is sending the conn_id field. To preserve compatability
@@ -120,6 +121,8 @@
  *
  * "no_extra_tiles" means that the extra, unknown (NODRAW) tiles will not be
  * sent to clients (previously used to help with drawing the terrain).
+ *
+ * "root_tech" restricts who can acquire technology
  */
 
 void init_our_capability(void)
Index: common/government.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/government.c,v
retrieving revision 1.39
diff -u -r1.39 government.c
--- common/government.c 4 Apr 2003 15:47:49 -0000       1.39
+++ common/government.c 29 Apr 2003 00:24:06 -0000
@@ -246,7 +246,10 @@
         government >= 0 && government < game.government_count);
 
   req = governments[government].required_tech;
-  if (!tech_exists(req)) {
+  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. */
     return FALSE;
   } else {
     return (get_invention(pplayer, req) == TECH_KNOWN
Index: common/packets.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.c,v
retrieving revision 1.245
diff -u -r1.245 packets.c
--- common/packets.c    17 Apr 2003 20:06:36 -0000      1.245
+++ common/packets.c    29 Apr 2003 00:24:06 -0000
@@ -2052,6 +2052,7 @@
   dio_put_uint8(&dout, packet->id);
   dio_put_uint8(&dout, packet->req[0]);
   dio_put_uint8(&dout, packet->req[1]);
+  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);
@@ -2082,6 +2083,7 @@
   dio_get_uint8(&din, &packet->id);
   dio_get_uint8(&din, &packet->req[0]);
   dio_get_uint8(&din, &packet->req[1]);
+  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.144
diff -u -r1.144 packets.h
--- common/packets.h    12 Apr 2003 18:24:42 -0000      1.144
+++ common/packets.h    29 Apr 2003 00:24:06 -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"
@@ -633,7 +634,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.61
diff -u -r1.61 tech.c
--- common/tech.c       7 Apr 2003 17:10:44 -0000       1.61
+++ common/tech.c       29 Apr 2003 00:24:06 -0000
@@ -95,7 +95,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;
   }
@@ -156,6 +157,25 @@
 }
 
 /**************************************************************************
+  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)
+{
+  if (!tech_exists(id)) {
+    return FALSE;
+  }
+
+  if (advances[id].root_req != A_NONE
+      && get_invention(pplayer, advances[id].root_req) != 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.
 **************************************************************************/
@@ -169,7 +189,7 @@
   /* assert(get_invention(pplayer, A_NONE) == TECH_KNOWN); */
 
   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) {
@@ -204,7 +224,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) {
@@ -226,7 +247,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       29 Apr 2003 00:24:06 -0000
@@ -15,6 +15,8 @@
 
 #include "shared.h"
 
+#include "nation.h" /* Nation_Type_id */
+
 struct player;
 
 typedef int Tech_Type_id;
@@ -77,7 +79,8 @@
   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];
+  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  29 Apr 2003 00:24:06 -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.68
diff -u -r1.68 diplhand.c
--- server/diplhand.c   17 Apr 2003 20:06:36 -0000      1.68
+++ server/diplhand.c   29 Apr 2003 00:24:07 -0000
@@ -147,6 +147,18 @@
       if (pclause->from == pplayer) {
        switch(pclause->type) {
        case CLAUSE_ADVANCE:
+          if (!tech_is_available(other, pclause->value)) {
+           /* It is impossible to give a technology to a civilization that
+            * can never possess it (the client should enforce this). */
+           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.36
diff -u -r1.36 diplomats.c
--- server/diplomats.c  5 Mar 2003 08:56:08 -0000       1.36
+++ server/diplomats.c  29 Apr 2003 00:24:07 -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.267
diff -u -r1.267 plrhand.c
--- server/plrhand.c    17 Apr 2003 20:06:36 -0000      1.267
+++ server/plrhand.c    29 Apr 2003 00:24:07 -0000
@@ -129,7 +129,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!"),
@@ -217,6 +218,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);
@@ -581,8 +584,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++;
     }
   }
@@ -599,8 +603,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.140
diff -u -r1.140 ruleset.c
--- server/ruleset.c    4 Apr 2003 15:47:50 -0000       1.140
+++ server/ruleset.c    29 Apr 2003 00:24:07 -0000
@@ -205,8 +205,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);
@@ -496,6 +496,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];
   
@@ -505,7 +506,9 @@
 
     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)",
@@ -551,6 +554,46 @@
     a++;
   }
 
+  /* Propagate a root tech up into the tech tree.  Thus if a technology
+   * X has Y has a root tech, then any technology requiring X also has
+   * Y as a root tech. */
+restart:
+  for (i = A_FIRST; i < num_techs; i++) {
+    a = &advances[i];
+    if (a->root_req != A_LAST && tech_exists(i)) {
+      int j;
+      bool out_of_order = FALSE;
+
+      /* Now find any tech depending on this technology and update it's
+       * root_req. */
+      for(j = A_FIRST; j < num_techs; j++) {
+        struct advance *b = &advances[j];
+        if ((b->req[0] == i || b->req[1] == i)
+            && b->root_req == A_LAST
+            && tech_exists(j)) {
+          b->root_req = a->root_req;
+         if (j < i) {
+           out_of_order = TRUE;
+          }
+        }
+      }
+
+      if (out_of_order) {
+       /* HACK: If we just changed the root_tech of a lower-numbered
+        * technology, we need to go back so that we can propagate the
+        * root_tech up to that technology's parents... */
+       goto restart;   
+      }
+    }
+  }
+  /* Now rename A_LAST to A_NONE for consistency's sake */
+  for (i = A_NONE; i < num_techs; i++) {
+    a = &advances[i];
+    if (a->root_req == A_LAST) {
+      a->root_req = A_NONE;
+    }
+  }
+
   /* Some more consistency checking: 
      Non-removed techs depending on removed techs is too
      broken to fix by default, so die.
@@ -2489,6 +2532,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/savegame.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/savegame.c,v
retrieving revision 1.116
diff -u -r1.116 savegame.c
--- server/savegame.c   22 Apr 2003 20:50:56 -0000      1.116
+++ server/savegame.c   29 Apr 2003 00:24:08 -0000
@@ -594,6 +594,7 @@
     p = (char *)name_order[secfile_lookup_int(file, "player%d.race", plrno)];
   }
   plr->nation = find_nation_by_name_orig(p);
+  init_tech(plr, game.tech); /* add techs from game and nation here */
 
   /* not all players have teams */
   if (section_file_lookup(file, "player%d.team", plrno)) {
@@ -677,8 +678,11 @@
   plr->revolution=secfile_lookup_int_default(file, 0, "player%d.revolution",
                                              plrno);
 
-  for(i=0; i<game.num_tech_types; i++)
-    set_invention(plr, i, (p[i]=='1') ? TECH_KNOWN : TECH_UNKNOWN);
+  for(i = 0; i < game.num_tech_types; i++) {
+    if (p[i] == '1') {
+      set_invention(plr, i, TECH_KNOWN);
+    }
+  }
 
   update_research(plr);
 

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] nation restrict tech v8 (PR#2464), Per I. Mathisen <=